无法在执行块中删除先前修改的新 table

Cannot drop priorly modified new table in execute block

我不太熟悉 FB 数据库及其微妙之处。 执行脚本时出现问题:

EXECUTE ibeblock
AS
BEGIN

-- 1. Create temporary table
execute statement 'recreate GLOBAL TEMPORARY table TMPTBL (ID bigint) /*on commit delete rows*/;';
commit;

-- 2. dummy fill of temporary table
insert into tmptbl (ID)
values (0xFE);
commit; -- not necessary

-- 3. perform some actions...

-- 4. Delete temporary table
execute statement 'drop table TMPTBL;';
commit; -- FAILURE!

END

脚本的思路很原始:1)创建临时文件table; 2)填写记录; 3) 使用填充记录对其他数据库对象执行操作; 4) 降低温度 table。 对于模拟,第 3 步无用(已跳过)。第 4 步导致错误 on commit:“此操作未为系统 tables 定义。元数据更新不成功。对象 TABLE“TMPTBL”位于采用。”。 table 既没有应用触发器也没有应用约束。显然,应该没有什么锁定温度 table.

请帮助解决。希望我错过了什么。 P.S.: FB 2.5, IBExpert 2017.12.13.1 用作数据库管理工具

你的代码有很多问题:

  1. 全局临时table旨在作为永久对象,它只是临时的内容(用于事务或连接持续时间)。所以通常你会创建一个全局临时 table 一次,而不是删除它,而是重用它的定义。

  2. 虽然从技术上讲您可以使用 execute statement 执行 DDL,但您不应该这样做,并且不能保证它会工作。您的代码具体是无法正常工作的示例之一。

    这里的问题是,您正试图在使用它的同一个事务中删除 table(尽管老实说,我很惊讶插入竟然起作用了,因为通常您不能插入到在同一事务中创建的 table。

    您在 TMPTBL 上执行的插入将标记 table 正在使用中,鉴于事务尚未提交,您不能删除 table:它是正在使用中。

  3. 你不应该在 PSQL 代码中调用提交(老实说,我认为这是不可能的)。

总之,你需要重新思考如何使用global temporary tables:定义一次,不要使用execute statement创建,而是单独创建。

如果您确实想要创建和删除它而不保留全局临时文件的定义 table,则在 execute block 之前创建它,提交,然后 execute block(只有插入和 'perform some actions'),提交,然后删除它(并提交)。

或者,您可以使用 execute statement ... with autonomous transaction 执行创建,在另一个 execute statement ... with autonomous transaction 中执行插入和 'perform some actions',最后在另一个 [=15= 中执行删除].但是,这会使您的代码非常脆弱,因此不推荐这种方法。

devops 人员再次迫使我寻找可靠的解决方案来提供数据库结构升级。要求:安全地结合DDL和DML语句;创建临时表的能力(用于大量选择);不要留下垃圾。当然,升级是在单个连接内处理的。

参考Mark给出的线索,加深了认识,做了很多实验。

这是真正有效的模板文件脚本(使用了 isql 本机实用程序):

SET TERM #;

-- 1. Create temporary table
EXECUTE BLOCK
AS
BEGIN
  execute statement 'recreate GLOBAL TEMPORARY table TMPTBL (ID bigint) /*on commit preserve rows*/;';
END#
commit#

-- Data manipulations
EXECUTE BLOCK
AS
  declare xid bigint;
BEGIN

-- 2. dummy fill of temporary table
begin
  insert into TMPTBL (ID) values (0xFE);
end

-- 3. perform some actions...
for
  select tt.ID
  from TMPTBL tt
  into :xid
do
begin
  -- use :xid var
end

END#
commit#


-- 4. Delete temporary table
EXECUTE BLOCK
AS
BEGIN
  execute statement 'drop table TMPTBL;';
END#
commit#

SET TERM ;#

可能对某人有用。 该死的,Firebird 真让人发疯!