【问题标题】: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).

【问题讨论】:

    标签: sql postgresql postgresql-9.2


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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-11
      • 1970-01-01
      相关资源
      最近更新 更多