2

我有一个 Firebird 数据库,我想确保每一行一次最多可以由一个用户编辑。 为此,我想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 时,我再次没有收到任何错误。

知道出了什么问题,以及如何正确地做到这一点?

4

1 回答 1

1

我发现了问题。在尝试将其作为EXECUTE BLOCK语句运行后,我实际上收到了一条有用的错误消息:“未知令牌:_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

这显然是无效的。在in循环name = trim(name);之后立即添加该行修复它。BEGINfor

于 2012-11-17T19:18:43.423 回答