简体   繁体   中英

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. For that, I want to put an OWNER column on every applicable table. 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:

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.

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".

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. 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); immediately after the BEGIN in the for loop fixed it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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