2015-01-07 79 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'允許你繞過這個你應該僅做,如果你沒有其他辦法解決這個(在這種特殊情況下,你可能沒有)。 –