如何更改Firebird上的CHECK约束?

时间:2015-01-07 21:54:23

标签: sql triggers constraints firebird

我有一个像这样的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重新编译代码的话。但也许有更好的方法?

2 个答案:

答案 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语句中遇到死锁。