2015-01-07 142 views
4

我有一个火鸟表是这样的:如何更改Firebird上的CHECK约束?

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 
); 

现在我需要另一个值添加到IN()列表中CHECK约束。我怎么做?

事情我试过到目前为止:

  • 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!),如果我能得到火鸟重新编译代码的方式。但也许有更好的方法?

回答

3

您需要删除和重新创建检查约束。

当你没有指定你的约束的名称,火鸟创建一个,所以你首先需要找到那名:

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')); 

将来你不需要去寻找约束的名字,因为你已经它。

+0

有没有一种方法以编程方式得到约束名,做好传入到一个文件这项工作'isql'? – theory

+0

我想通过编程方式做到这一点,并将其发布在单独的答案中。 – theory

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声明死锁。

+1

提醒一句:虽然这样的工作,执行从PSQL(如EXECUTE BLOCK)DDL是不允许的,因为这些类型的具有与PSQL如何编译和执行错误(+附加的原因正是 - 在存储过程的情况下 - 存储),虽然使用'EXECUTE STATEMENT'允许你绕过这个你应该仅做,如果你没有其他办法解决这个(在这种特殊情况下,你可能没有)。 –