Postgresql

檢索特定於列的檢查約束的名稱

  • April 6, 2021

PostgreSQL 12

當我重命名表中的列時,我也想動態重命名匹配的檢查約束。

我有一個假設的表格:

CREATE TABLE hypothetical_table (
 id SERIAL PRIMARY KEY,
 some_col text,
 some_col_also text
);

有以下限制:

ALTER TABLE hypothetical_table ADD CONSTRAINT some_col_length_>_5 CHECK(char_length(some_col) > 5);

ALTER TABLE hypothetical_table ADD CONSTRAINT some_col_also_length_>_5 CHECK(char_length(some_col_also) > 5);

我不知道列可能有什麼限制。我知道它們以列名為前綴。但是,就像some_col上面的約束一樣,該前綴可能與另一列的 ( some_col_also) 匹配。

當我重命名此表中的列時,我也想重命名約束,以匹配新的列名。

那麼,如果我要重命名some_col,如何選擇與該列關聯的所有檢查約束?

我嘗試pg_catalog.pg_constraint使用pg_catalog.pg_attributeON con.conkey = pga.attnumconkey未嵌套)加入,但這會返回許多與該列無關的約束。

如何選擇與該列關聯的所有檢查約束?

pg_constraint.conkey是一個數組列,所以我們另外加入a.attnum = ANY(c.conkey) 關係的oid。像:

SELECT conname -- pg_get_constraintdef(oid), *
FROM   pg_constraint c
JOIN   pg_attribute  a ON a.attrelid = c.conrelid     -- !
                     AND a.attnum   = ANY(c.conkey)  -- !
WHERE  c.conrelid = 'hypothetical_table'::regclass
AND    c.contype = 'c'  -- c = check constraint
AND    a.attname = 'some_col';

但我懷疑你的總體目標:

當我重命名表中的列時,我也想動態重命名匹配的檢查約束。

CHECK在 Postgres 中,約束總是約束,並且可以引用任意數量的表列。即使公式化為列約束!手冊:

列檢查約束

SQL 標準規定CHECK列約束只能引用它們適用的列;只有CHECK表約束可以引用多個列。PostgreSQL 不強制執行此限制;它對待列和表檢查約束是一樣的。

所以some_colandsome_col_also可以同時引用(多次)。兩者都可以在約束名稱中。除非您可以依賴嚴格的命名約定,否則我看不出一個完全動態的解決方案如何是防彈的。(你真的可以嗎?)。以下是對some_color的引用some_col_also嗎?

some_col_also_is_a_fruit  -- oh, wait!

重寫約束表達式本身也需要注意。

引用自:https://dba.stackexchange.com/questions/289314