如何更改 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.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
.
中编译的
用新检查创建一个新的 table,复制数据,删除旧的 table 并重命名新的 table。不过好像是一个cannot rename a Firebird table,所以我没法让新的table和旧的重名
我怀疑更新 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;
我有一个 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.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
. 中编译的
用新检查创建一个新的 table,复制数据,删除旧的 table 并重命名新的 table。不过好像是一个cannot rename a Firebird table,所以我没法让新的table和旧的重名
我怀疑更新 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;