您可以查询系统目录 for 独特的约束, 尤其pg_constraint
and 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;
The 对象标识符类型 regclass
有助于明确识别您的桌子。
系统目录信息功能pg_get_constraintdef()为您提供格式良好的信息,这对于您的请求来说并不是绝对必要的。
还使用数组运算符 <@
and @>
确保数组完全匹配。 (列的顺序未知。)系统列是smallint
and smallint[]
分别。投射到integer
使其与这些操作员一起工作。
直接在系统目录中查找列名时,列名区分大小写。如果你没有双引号C1
and C2
在创建时,你必须使用c1
and c2
在此背景下。
-
也可以有多列主键约束强化独特性。要在查询中覆盖它,请改用:
WHERE c.contype IN ('u', 'p')
基于 @Roman 的小提琴,这个还演示了 pk 情况:
->SQLfiddle
唯一索引
上述两个(unique & 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[]
.
请注意,目录表的实现可能会随着专业的不同而改变。这些查询不太可能中断,但有可能。