[英]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.