如何更改 Firebird 上的 CHECK 约束?

How do I alter a CHECK constraint on Firebird?

我有一个 Firebird table 这样的:

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 是可行的方法(我知道!),如果我能让 Firebird 重新编译代码就好了。但也许有更好的方法?

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

由于您没有为约束指定名称,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'));

以后您不需要查找约束名称,因为您已经找到了。

以下是动态执行的方法:

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 语句上陷入僵局。

以下是动态执行的方法:

EXECUTE BLOCK RETURNS (STMT VARCHAR(1000)) AS
BEGIN
    SELECT TRIM(R.RDB$CONSTRAINT_NAME)
    FROM RDB$RELATION_CONSTRAINTS R
    WHERE R.RDB$RELATION_NAME = 'TABLE_NAME'
    AND UPPER(R.RDB$CONSTRAINT_TYPE) = UPPER('PRIMARY KEY')
    INTO :STMT;

    IF (:STMT IS NOT NULL) THEN
    BEGIN
        EXECUTE STATEMENT 'ALTER TABLE TABLE_NAME DROP CONSTRAINT ' || :STMT || ';';
        EXECUTE STATEMENT 'ALTER TABLE TABLE_NAME ADD CONSTRAINT ' || :STMT || ' PRIMARY KEY (FIELD1, FIELD2, FIELD3);';
    END
    ELSE
    BEGIN
        EXECUTE STATEMENT 'ALTER TABLE FIELD1 ADD CONSTRAINT PK_PRIMARY_NAME PRIMARY KEY (FIELD1, FIELD2, FIELD3);';
    END
END;