如何查找给定列是不是存在唯一键约束
Posted
技术标签:
【中文标题】如何查找给定列是不是存在唯一键约束【英文标题】:How to find whether unique key constraint exists for given columns如何查找给定列是否存在唯一键约束 【发布时间】:2013-11-20 04:18:56 【问题描述】:我正在编写一个 perl 脚本,我需要在其中运行更新查询。但我需要检查更新 sql 命令是否不违反唯一键约束。
所以如果我有一张表tb(C1,C2,C3)
并且我的更新查询是这样的:
update tb set C1='b1' where C2='a1' ;
有没有办法找出列C1,C2
是否存在唯一键约束在尝试更新之前?即:UNIQUE(C1,C2)
.
【问题讨论】:
【参考方案1】:您可以在system catalogs 中查询唯一约束,尤其是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;
object identifer type regclass
有助于明确识别您的表。
系统目录信息功能pg_get_constraintdef()
为您提供格式良好的信息,这对于您的请求并非绝对必要。
还使用array operators <@
和@>
来确保数组完全匹配。 (列顺序未知。)系统列分别为smallint
和smallint[]
。转换为 integer
以使其与这些运算符一起使用。
直接在系统目录中查找列名时区分大小写。如果您在创建时没有双引号 C1
和 C2
,则必须在此上下文中使用 c1
和 c2
。
也可能存在一个强制唯一性的多列主键约束。要在查询中覆盖它,请改用:
WHERE c.contype IN ('u', 'p')
在@Roman's fiddle 的基础上,这个也演示了 pk 案例:
->SQLfiddle
唯一索引
以上两个(唯一和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[]
来处理它。
请注意,目录表的实现可能会因主要而异。这些查询不太可能中断,但有可能。
【讨论】:
+1,我几乎完成了我的回答,但您的回答更具描述性。这是您回答的 sql fiddle - sqlfiddle.com/#!12/e6697/10。我不太喜欢大写的 SQL,但我认为这完全是主观的 :) @RomanPekar:在完成之前丢掉好工作很痛苦。我知道那种感觉,对不起。谢谢你的小提琴。 @Anant:我后来意识到,您可能缺少普通的唯一索引(没有明确的约束)。请参阅修改后的答案。【参考方案2】:您可以通过检查pg_catalog.pg_constraint
表来确定是否存在约束(不可移植),但这不会告诉您插入是否会违反约束,并且它即使可以,也很容易发生比赛。
正确的做法是尝试插入并适当地处理失败。
【讨论】:
以上是关于如何查找给定列是不是存在唯一键约束的主要内容,如果未能解决你的问题,请参考以下文章