[英]How to find whether unique key constraint exists for given columns
我正在使用perl腳本,我需要運行更新查詢。 但我需要檢查更新sql命令是否違反唯一鍵約束。 所以,如果我有一個表tb(C1,C2,C3)
,我的更新查詢如下:
update tb set C1='b1' where C2='a1' ;
有沒有辦法在嘗試更新之前查找列C1,C2
是否存在唯一鍵約束? 即: UNIQUE(C1,C2)
。
您可以在系統目錄中查詢唯一約束 ,尤其是pg_constraint
和pg_attribute
:
SELECT c.conname, pg_get_constraintdef(c.oid)
FROM pg_constraint c
JOIN (
SELECT array_agg(attnum::int) AS attkey
FROM pg_attribute
WHERE attrelid = 'tb'::regclass -- table name optionally schema-qualified
AND attname = ANY('{c1,c2}')
) a ON c.conkey::int[] <@ a.attkey AND c.conkey::int[] @> a.attkey
WHERE c.contype = 'u'
AND c.conrelid = 'tb'::regclass;
對象標識符類型 regclass
有助於明確標識您的表。
系統目錄信息函數pg_get_constraintdef()
為您提供格式良好的信息,這對您的請求並不是絕對必要的。
還使用數組運算符 <@
和@>
來確保數組完全匹配。 (列的順序未知。)系統列分別為smallint
和smallint[]
。 轉換為integer
以使其與這些運算符一起使用。
直接在系統目錄中查找列名稱時區分大小寫。 如果在創建時沒有雙引號C1
和C2
,則必須在此上下文中使用c1
和c2
。
還可能存在強制唯一性的多列主鍵約束 。 要在查詢中使用,請改為使用:
WHERE c.contype IN ('u', 'p')
在@ Roman的小提琴的基礎上,這個也展示了pk案例:
以上兩者(唯一和pk約束)都是通過唯一索引實現的。 此外,還可以存在與正式聲明的唯一約束有效相同的唯一索引 。 要捕獲所有這些 ,請以類似的方式查詢系統目錄pg_index
:
SELECT c.relname AS idx_name
FROM (
SELECT indexrelid, string_to_array(indkey::text, ' ')::int[] AS indkey
FROM pg_index
WHERE indrelid = 'tb'::regclass
AND indisunique -- contains "indisprimary"
) i
JOIN (
SELECT array_agg(attnum::int) AS attkey
FROM pg_attribute
WHERE attrelid = 'tb'::regclass
AND attname = ANY('{c1,c2}')
) a ON i.indkey <@ a.attkey AND i.indkey @> a.attkey
JOIN pg_class c ON c.oid = i.indexrelid;
這里的特殊困難是內部類型int2vector
。 我通過轉換文本並轉換為int[]
來處理它。
請注意,目錄表的實現可能會在主要內容中發生變化。 不太可能這些查詢中斷,但可能。
您可以通過檢查pg_catalog.pg_constraint
表來查明是否存在約束(不可移植),但這不會告訴您插入是否會違反約束,即使可能也會出現競爭。
正確的做法是嘗試插入並適當地處理故障。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.