无法在执行块中删除先前修改的新 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 用作数据库管理工具
你的代码有很多问题:
全局临时table旨在作为永久对象,它只是临时的内容(用于事务或连接持续时间)。所以通常你会创建一个全局临时 table 一次,而不是删除它,而是重用它的定义。
虽然从技术上讲您可以使用 execute statement
执行 DDL,但您不应该这样做,并且不能保证它会工作。您的代码具体是无法正常工作的示例之一。
这里的问题是,您正试图在使用它的同一个事务中删除 table(尽管老实说,我很惊讶插入竟然起作用了,因为通常您不能插入到在同一事务中创建的 table。
您在 TMPTBL
上执行的插入将标记 table 正在使用中,鉴于事务尚未提交,您不能删除 table:它是正在使用中。
你不应该在 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 真让人发疯!
我不太熟悉 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 用作数据库管理工具
你的代码有很多问题:
全局临时table旨在作为永久对象,它只是临时的内容(用于事务或连接持续时间)。所以通常你会创建一个全局临时 table 一次,而不是删除它,而是重用它的定义。
虽然从技术上讲您可以使用
execute statement
执行 DDL,但您不应该这样做,并且不能保证它会工作。您的代码具体是无法正常工作的示例之一。这里的问题是,您正试图在使用它的同一个事务中删除 table(尽管老实说,我很惊讶插入竟然起作用了,因为通常您不能插入到在同一事务中创建的 table。
您在
TMPTBL
上执行的插入将标记 table 正在使用中,鉴于事务尚未提交,您不能删除 table:它是正在使用中。你不应该在 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 真让人发疯!