在编写大型事务(大量插入、删除、更新)并因此违反 Informix(v10,但也应适用于其他版本)中的约束时,我收到一条不太有用的消息,例如,我违反了约束 r190_710。我怎样才能找出哪些表和键被某个约束所覆盖,我只知道它的名称?
7 回答
Tony Andrews 建议(指向 URL 的不同端点):
从Informix Guide to SQL: Reference看来,您应该查看系统目录表 SYSCONSTRAINTS 和 SYSINDICES。
该手册中描述了 Informix 系统目录。
毫无疑问,SysConstraints 表是分析约束的起点;您可以在该表中找到约束名称,然后您可以从那里找到其他详细信息。
但是,您还必须查看其他表,而不仅仅是(甚至直接)SysIndices。
例如,我的数据库中的表有很多 NOT NULL 约束。对于那些,约束类型为“N”,无需在其他地方查找更多信息。
约束类型“P”表示主键;这需要通过 SysIndexes 视图或 SysIndices 表进行更多分析。同样,约束类型“U”表示唯一约束,需要来自 SysIndexes 视图或 SysIndices 表的额外信息。
'C' 的约束类型表示检查约束;约束的文本(和二进制编译形式)可在 SysChecks 表中找到(数据类型为“T”和“B”;数据或多或少使用 Base-64 编码,但没有“=”填充最后并为 62 和 63 使用不同的字符)。
最后,约束类型“R”表示参照完整性约束。您可以使用 SysReferences 表来找出引用了哪个表,并使用 SysIndexes 或 SysIndices 来确定使用了引用和被引用表上的哪些索引,并从中可以发现相关的列。这会变得很毛茸茸!
表中具有约束的列
SELECT
a.tabname, b.constrname, d.colname
FROM
systables a, sysconstraints b, sysindexes c, syscolumns d
WHERE
a.tabname = 'your_table_name_here'
AND
b.tabid = a.tabid
AND
c.idxname = b.idxname
AND
d.tabid = a.tabid
AND
(
d.colno = c.part1 or
d.colno = c.part2 or
d.colno = c.part3 or
d.colno = c.part4 or
d.colno = c.part5 or
d.colno = c.part6 or
d.colno = c.part7 or
d.colno = c.part8 or
d.colno = c.part9 or
d.colno = c.part10 or
d.colno = c.part11 or
d.colno = c.part12 or
d.colno = c.part13 or
d.colno = c.part14 or
d.colno = c.part15 or
d.colno = c.part16
)
ORDER BY
a.tabname,
b.constrname,
d.colname
我一直在使用以下查询来获取有关不同类型约束的更多信息。它基于系统表中的一些探索和关于系统目录的一些解释。
sysconstraints.constrtype 表示约束的类型:
- P = 主键
- U = 唯一键/备用键
- N = 不为空
- C = 检查
- R = 参考/外键
select
tab.tabname,
constr.*,
chk.*,
c1.colname col1,
c2.colname col2,
c3.colname col3,
c4.colname col4,
c5.colname col5
from sysconstraints constr
join systables tab on tab.tabid = constr.tabid
left outer join syschecks chk on chk.constrid = constr.constrid and chk.type = 'T'
left outer join sysindexes i on i.idxname = constr.idxname
left outer join syscolumns c1 on c1.tabid = tab.tabid and c1.colno = abs(i.part1)
left outer join syscolumns c2 on c2.tabid = tab.tabid and c2.colno = abs(i.part2)
left outer join syscolumns c3 on c3.tabid = tab.tabid and c3.colno = abs(i.part3)
left outer join syscolumns c4 on c4.tabid = tab.tabid and c4.colno = abs(i.part4)
left outer join syscolumns c5 on c5.tabid = tab.tabid and c5.colno = abs(i.part5)
where constr.constrname = 'your constraint name'
获取受约束“r190_710”影响的表:
select TABNAME from SYSTABLES where TABID IN
(select TABID from sysconstraints where CONSTRID IN
(select CONSTRID from sysreferences where PTABID IN
(select TABID from sysconstraints where CONSTRNAME= "r190_710" )
)
);
通过浏览 www.iiug.org(国际 Informix 用户组),我发现了这个不太容易的解决方案。
(1) 从约束名称中获取引用约束数据(可以通过将“AND sc.constrname = ?”替换为“AND st.tabname MATCHES ?”来获取表的所有约束)。该语句在这里选择了一些不必要的字段,因为它们在其他情况下可能会很有趣。
SELECT si.part1, si.part2, si.part3, si.part4, si.part5,
si.part6, si.part7, si.part8, si.part9, si.part10,
si.part11, si.part12, si.part13, si.part14, si.part15, si.part16,
st.tabname, rt.tabname as reftable, sr.primary as primconstr,
sr.delrule, sc.constrid, sc.constrname, sc.constrtype,
si.idxname, si.tabid as tabid, rc.tabid as rtabid
FROM 'informix'.systables st, 'informix'.sysconstraints sc,
'informix'.sysindexes si, 'informix'.sysreferences sr,
'informix'.systables rt, 'informix'.sysconstraints rc
WHERE st.tabid = sc.tabid
AND st.tabtype != 'Q'
AND st.tabname NOT MATCHES 'cdr_deltab_[0-9][0-9][0-9][0-9][0-9][0-9]*'
AND rt.tabid = sr.ptabid
AND rc.tabid = sr.ptabid
AND sc.constrid = sr.constrid
AND sc.tabid = si.tabid
AND sc.idxname = si.idxname
AND sc.constrtype = 'R'
AND sc.constrname = ?
AND sr.primary = rc.constrid
ORDER BY si.tabid, sc.constrname
(2) 使用part1-part16来判断哪一列受约束:part[n]包含一个非0的值,包含使用列的列号。使用 (3) 查找列的名称。
如果 constrtype 为 'R'(引用),请使用以下语句查找引用表的部分:
SELECT part1, part2, part3, part4, part5, part6, part7, part8,
part9, part10, part11, part12, part13, part14, part15, part16
FROM 'informix'.sysindexes si, 'informix'.sysconstraints sc
WHERE si.tabid = sc.tabid
AND si.idxname = sc.idxname
AND sc.constrid = ? -- primconstr from (1)
(3) 现在可以使用 (1) 中的 tabid 和 rtabid(用于引用约束)来获取表的列,如下所示:
SELECT colno, colname
FROM 'informix'.syscolumns
WHERE tabid = ? -- tabid(for referenced) or rtabid(for referencing) from (1)
AND colno = ? -- via parts from (1) and (2)
ORDER BY colno
(4) 如果constrtype是'C',则得到如下检查信息:
SELECT type, seqno, checktext
FROM 'informix'.syschecks
WHERE constrid = ? -- constrid from (1)
确实毛茸茸的
从Informix Guide to SQL: Reference看来,您应该查看系统目录表 SYSCONSTRAINTS 和 SYSINDICES。
如果你的约束是命名constraint_c6
的,这里是如何转储它的定义(好吧,你仍然需要连接行,因为它们将被空格分隔):
OUTPUT TO '/tmp/constraint_c6.sql' WITHOUT HEADINGS
SELECT ch.checktext
FROM syschecks ch, sysconstraints co
WHERE ch.constrid = co.constrid
AND ch.type = 'T' -- text lines only
AND co.constrname = 'constraint_c6'
ORDER BY ch.seqno;