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

标签 sql postgresql postgresql-9.2

我正在编写一个 perl 脚本,我需要在其中运行更新查询。但是我需要检查 update sql 命令是否不违反唯一键约束。 因此,如果我有一个表 tb(C1,C2,C3) 并且我的更新查询如下:

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

有没有一种方法可以在 尝试更新之前,确定 C1,C2 列是否存在唯一键约束?即:UNIQUE(C1,C2)

最佳答案

可以查询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有助于明确识别您的 table 。

  • 系统目录信息函数 pg_get_constraintdef() 获取格式良好的信息,这对于您的请求而言并非绝对必要。

  • 同时使用 array operators <@@>确保数组完全匹配。 (列的顺序未知。)系统列是 smallintsmallint[]分别。转换到integer使其与这些运营商合作。

  • 直接在系统目录中查找时,列名区分大小写。如果你没有双引号 C1C2在创建时,你必须使用 c1c2在这种情况下。

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

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

建立在@Roman 的 fiddle 上,这个也演示了 pk 案例:

->SQLfiddle

唯一索引

以上两个(unique & pk constraints)都是通过unique index的方式实现的。此外,还可以有唯一索引有效地与正式声明的唯一约束相同。要捕获所有,请查询系统目录 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[] 来处理它.

请注意,目录表的实现可能会因专业而异。这些查询不太可能中断,但有可能。

关于sql - 如何查找给定列是否存在唯一键约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20087259/

相关文章:

mysql - SQL 聚合函数 MAX/MIN/AVG/COUNT 的子查询等价物是什么

SQL查询以根据分组依据获取与列的最大值对应的另一列的值

postgresql - Postgres : 'role does not exist' using dblink, 但确实如此

从备份恢复 PostgreSQL 数据库

mysql - "QUERY"添加值而不覆盖以前的值

mysql - 单表之间一对一的SQL

django - 在 Django 中创建数据库驱动的主导航?

sql - 从函数 postgresql 输出到屏幕并记录文件

postgresql - 根据用户群更改时区

arrays - PostgreSql遍历数组获取同一列下多行的结果