简体   繁体   English

如何创建存储过程以确保每个表都包含某些列?

[英]How do I create a stored proc to ensure that every table contains certain columns?

I've got a Firebird database where I want to ensure that every row can be edited by at most one user at a time. 我有一个Firebird数据库, 我想确保每个行一次最多可以编辑一个用户。 For that, I want to put an OWNER column on every applicable table. 为此,我想在每个适用的表上放置一个OWNER列。 It would be a bit tedious to do this by hand for every table, so I tried writing up a way to automate it. 手动为每个表执行此操作有点乏味,因此我尝试编写一种自动执行此操作的方法。 First, create a view that gives you all tables that need to be updated: 首先,创建一个视图,为您提供所有需要更新的表:

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;

This works fine. 这很好。

Then, create a proc to do the maintenance: 然后,创建一个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

But when I run this one, nothing happens. 但是当我运行此程序时,什么也没发生。 No errors are reported, but no tables get updated with the new bookkeeping. 没有错误的报告,但没有表格更新与新的簿记。 When I run the proc under the Hopper proc debugger for Firebird, again I don't get any errors. 当我在Firebird的Hopper proc调试器下运行proc时,再次没有得到任何错误。

Any idea what's going wrong, and how to do this right? 知道发生了什么问题以及如何正确执行此操作吗?

I found the problem. 我发现了问题。 After attempting to run it as an EXECUTE BLOCK statement, I actually got a useful error message: "Unknown token: _OWNER". 尝试将其作为EXECUTE BLOCK语句运行后,实际上收到了一条有用的错误消息:“未知令牌:_OWNER”。

Apparently this does not show up when running the proc under the Hopper debugger, but the result of the metadata select that contains the table names has trailing spaces. 显然,在Hopper调试器下运行proc时,这不会显示,但是包含表名的元数据选择结果带有尾随空格。 So the following line: 所以下面这行:

replace('ALTER TABLE %T ADD CONSTRAINT FK_%T_OWNER foreign key (OWNER) references USERS', '%T', :name)

resolves to something like: 解决如下问题:

ALTER TABLE TABLENAME ADD CONSTRAINT FK_TABLENAME      _OWNER foreign key (OWNER) references USERS

which is obviously invalid. 这显然是无效的。 Adding the line name = trim(name); 添加行name = trim(name); immediately after the BEGIN in the for loop fixed it. for循环中的BEGIN之后立即将其修复。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM