Ana*_*ant 4 sql postgresql postgresql-9.2
我正在使用perl脚本,我需要运行更新查询.但我需要检查更新sql命令是否违反唯一键约束.所以,如果我有一个表tb(C1,C2,C3),我的更新查询如下:
update tb set C1='b1' where C2='a1' ;
Run Code Online (Sandbox Code Playgroud)
有没有办法C1,C2 在尝试更新之前查找列是否存在唯一键约束?即:UNIQUE(C1,C2).
您可以通过查询系统目录的唯一约束,尤其是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;
Run Code Online (Sandbox Code Playgroud)
在对象类型IDENTIFER regclass有助于明确识别您的餐桌.
系统目录信息功能pg_get_constraintdef()可以为您提供格式良好的信息,这对您的请求来说并不是绝对必要的.
还使用数组运算符 <@并@>确保数组完全匹配.(列的顺序未知.)系统列分别为smallint和smallint[].转换integer为使其与这些运算符一起工作.
直接在系统目录中查找列名称时区分大小写.如果您没有双引号,C1并且C2在创建时,您必须使用c1并c2在此上下文中.
还可能存在强制唯一性的多列主键约束.要在查询中使用,请改为使用:
WHERE c.contype IN ('u', 'p')
Run Code Online (Sandbox Code Playgroud)在@ Roman的小提琴的基础上,这个也展示了pk案例:
以上两者(唯一和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;
Run Code Online (Sandbox Code Playgroud)
这里的特殊困难是内部类型int2vector.我通过投射文本和转换来处理它int[].
请注意,目录表的实现可能会在主要内容中发生变化.不太可能这些查询中断,但可能.
| 归档时间: |
|
| 查看次数: |
2623 次 |
| 最近记录: |