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

时间:2013-11-20 04:18:56

标签: sql postgresql postgresql-9.2

我正在处理perl脚本,我需要运行更新查询。但我需要检查更新sql命令是否违反唯一键约束。 所以,如果我有一个表tb(C1,C2,C3),我的更新查询就像:

update tb set C1='b1' where C2='a1' ;

在尝试更新之前,有没有办法找到列C1,C2 是否存在唯一键约束?即:UNIQUE(C1,C2)

2 个答案:

答案 0 :(得分:5)

您可以在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 <@@>来确保数组完全匹配。 (列的顺序未知。)系统列分别为smallintsmallint[]。转换为integer以使其与这些运营商一起使用。

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

  • 还可能存在多列主键约束强制唯一性。要在查询中使用,请改为使用:

    WHERE  c.contype IN ('u', 'p')
    

在@ Roman的小提琴的基础上,这个也演示了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 :(得分:1)

您可以通过检查pg_catalog.pg_constraint表来查明约束是否存在(不可移植),但这不会告诉您插入是否会违反约束 ,即使可能,也很容易发生比赛。

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