我有一个Firebird数据库I want to ensure that every row can be edited by at most one user at a time.为此,我想在每个适用的表上放置一个OWNER
列。为每张桌子手动执行此操作会有点乏味,所以我尝试编写一种自动化方法。首先,创建一个视图,为您提供所有需要更新的表:
CREATE VIEW OWNABLE_TABLES_V
(
NAME
)
AS
SELECT tables.RDB$RELATION_NAME
FROM RDB$RELATIONS tables
WHERE (tables.RDB$SYSTEM_FLAG=0) and (tables.rdb$view_source is null)
and not exists (
--table containing names of tables that are exceptions to the rule
select name from META_NOT_OWNABLE
where name = tables.RDB$RELATION_NAME)
and not exists (
select * from RDB$RELATION_FIELDS fields
where (fields.RDB$RELATION_NAME = tables.RDB$RELATION_NAME)
and (fields.RDB$FIELD_NAME = 'OWNER'))
order by tables.RDB$RELATION_NAME;
这很好用。
然后,创建一个proc来进行维护:
CREATE PROCEDURE PREPARE_OWNERSHIP
AS
declare variable name varchar(31);
BEGIN
for select NAME from OWNABLE_TABLES_V into :name do
BEGIN
execute statement replace('ALTER TABLE %T ADD OWNER INTEGER', '%T', :name)
with autonomous transaction;
execute statement replace('ALTER TABLE %T ADD OWNER_TIMEOUT TIMESTAMP', '%T', :name)
with autonomous transaction;
execute statement replace('ALTER TABLE %T ADD CONSTRAINT FK_%T_OWNER foreign key (OWNER) references USERS', '%T', :name)
with autonomous transaction;
END
END
但是当我运行这个时,没有任何反应。没有报告错误,但没有使用新的簿记更新表。当我在Firebird的Hopper proc调试器下运行proc时,我再也没有出现任何错误。
知道出了什么问题,以及如何做到这一点?
答案 0 :(得分:1)
我发现了问题。在尝试将其作为EXECUTE BLOCK
语句运行后,我实际上收到了一条有用的错误消息:“Unknown token:_OWNER”。
显然,当在Hopper调试器下运行proc时,这不显示,但包含表名的元数据选择的结果具有尾随空格。所以以下一行:
replace('ALTER TABLE %T ADD CONSTRAINT FK_%T_OWNER foreign key (OWNER) references USERS', '%T', :name)
解析为:
ALTER TABLE TABLENAME ADD CONSTRAINT FK_TABLENAME _OWNER foreign key (OWNER) references USERS
显然无效。在name = trim(name);
循环中的BEGIN
之后立即添加行for
修复了该行。