我有一个像这样的Firebird表:
CREATE TABLE events (
event VARCHAR(6) NOT NULL
CHECK (event IN ('deploy', 'revert', 'fail')),
change_id CHAR(40) NOT NULL,
change VARCHAR(512) NOT NULL
);
现在我需要在CHECK约束中的IN()
列表中添加另一个值。我该怎么做?
到目前为止我尝试过的事情:
更新RDB$TRIGGERS.RDB$TRIGGER_SOURCE
中的值:
UPDATE RDB$TRIGGERS
SET RDB$TRIGGER_SOURCE = 'CHECK (event IN (''deploy'', ''revert'', ''fail'', ''merge''))'
WHERE RDB$TRIGGER_SOURCE = 'CHECK (event IN (''deploy'', ''revert'', ''fail''))';
似乎不起作用,因为触发器是在RDB$TRIGGERS.RDB$TRIGGER_BLR
中编译的。
使用新检查创建新表,复制数据,删除旧表并重命名新表。但是,似乎有一个cannot rename a Firebird table,所以我不能让新表与旧表名称相同。
我怀疑更新RDB$TRIGGERS
是要走的路(idk!),如果我能让Firebird重新编译代码的话。但也许有更好的方法?
答案 0 :(得分:3)
您需要删除并重新创建检查约束。
由于您没有为约束指定名称,Firebird创建了一个名称,因此您首先需要找到该名称:
select trim(cc.rdb$constraint_name), trg.rdb$trigger_source
from rdb$relation_constraints rc
join rdb$check_constraints cc on rc.rdb$constraint_name = cc.rdb$constraint_name
join rdb$triggers trg on cc.rdb$trigger_name = trg.rdb$trigger_name
where rc.rdb$relation_name = 'EVENTS'
and rc.rdb$constraint_type = 'CHECK'
and trg.rdb$trigger_type = 1;
我刚刚添加了触发源,仅供参考。
获得名称后,可以删除它,例如
alter table events drop constraint integ_27;
然后添加新约束:
alter table events
add constraint check_event_type
CHECK (event IN ('deploy', 'revert', 'fail', 'merge'));
将来您不需要查找约束名称,因为您已经拥有它。
答案 1 :(得分:1)
以下是如何动态完成的:
SET AUTOddl OFF;
SET TERM ^;
EXECUTE BLOCK AS
DECLARE trig VARCHAR(64);
BEGIN
SELECT TRIM(cc.rdb$constraint_name)
FROM rdb$relation_constraints rc
JOIN rdb$check_constraints cc ON rc.rdb$constraint_name = cc.rdb$constraint_name
JOIN rdb$triggers trg ON cc.rdb$trigger_name = trg.rdb$trigger_name
WHERE rc.rdb$relation_name = 'EVENTS'
AND rc.rdb$constraint_type = 'CHECK'
AND trg.rdb$trigger_type = 1
INTO trig;
EXECUTE STATEMENT 'ALTER TABLE EVENTS DROP CONSTRAINT ' || trig;
END^
SET TERM ;^
COMMIT;
ALTER TABLE events ADD CONSTRAINT check_event_type CHECK (
event IN ('deploy', 'revert', 'fail', 'merge')
);
COMMIT;
我必须禁用AUTOddl
并进行显式提交,否则我会在ALTER TABLE ADD CONSTRAINT
语句中遇到死锁。