如何查找给定列是不是存在唯一键约束

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_constraintpg_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 &lt;@@&gt; 来确保数组完全匹配。 (列顺序未知。)系统列分别为smallintsmallint[]。转换为 integer 以使其与这些运算符一起使用。

直接在系统目录中查找列名时区分大小写。如果您在创建时没有双引号 C1C2,则必须在此上下文中使用 c1c2

也可能存在一个强制唯一性的多列主键约束。要在查询中覆盖它,请改用:

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 表来确定是否存在约束(不可移植),但这不会告诉您插入是否会违反约束,并且它即使可以,也很容易发生比赛。

正确的做法是尝试插入并适当地处理失败。

【讨论】:

以上是关于如何查找给定列是不是存在唯一键约束的主要内容,如果未能解决你的问题,请参考以下文章

查找列是不是具有唯一约束

SQL的主键,约束 有啥用

约束的类型

如何更新 postgreSQL 唯一键约束

数据库相关练习题

5-05约束的类型