为什么在Firebird的存储过程中不允许使用临时表?

时间:2015-11-28 14:58:48

标签: database stored-procedures temp-tables firebird-3.0

我正在尝试在Firebird数据库中的存储过程中创建临时表。

我的存储过程列表:

SET TERM ^ ;

CREATE PROCEDURE initNATIONALHEALTHFUNDS

AS BEGIN

  CREATE GLOBAL TEMPORARY TABLE temp_FUNDS 
  (
    NATIONALHEALTHFUNDID Integer NOT NULL,
    NAME Varchar(128) NOT NULL,
    CODE Integer NOT NULL
  )
  ON COMMIT PRESERVE ROWS;
  commit;

 INSERT INTO tempFUNDS (NATIONALHEALTHFUNDID, CODE, NAME)  VALUES ( 01 ,01 , 'Some Foundation');


  MERGE INTO NATIONALHEALTHFUNDS  AS target 
   USING tempFUNDS AS source 
   ON target.NATIONALHEALTHFUNDID = source.NATIONALHEALTHFUNDID
   WHEN NOT MATCHED THEN 
    INSERT (NATIONALHEALTHFUNDID, CODE, NAME) VALUES (source.NATIONALHEALTHFUNDID, source.CODE, source.NAME);

  drop  TABLE tempFUNDS;
END^

SET TERM ; ^

每次我尝试创建此过程时都会收到错误:

    Engine Code    : 335544569
Engine Message :
Dynamic SQL Error
SQL error code = -104
Token unknown - line 7, column 3
CREATE


Total execution time: 0.015s

我做错了什么? Firebird 3.0 RC

提前谢谢你 罗伯特

2 个答案:

答案 0 :(得分:5)

Firebird不允许您在存储过程中使用DDL,因此PSQL中不允许使用CREATE语句。如answer by lad2025所示,您可以使用EXECUTE STATEMENT来解决此限制。

然而,global temporary table背后的想法是你创建它一次,它们会继续存在,以便以后可以使用。数据仅对创建数据的连接可见,并且在事务提交(ON COMMIT DELETE ROWS)或连接关闭(ON COMMIT PRESERVE ROWS)之后删除数据,具体取决于全局临时表的类型。

来自语言参考更新:

  

全局临时表具有持久性元数据,但其内容是事务绑定(默认)或连接绑定。每个事务或连接都有自己的GTT私有实例,与其他所有实例隔离。仅在引用GTT时创建实例,并在事务结束或断开连接时销毁实例。

因此,不要尝试在存储过程中创建全局临时表,而是首先创建它,然后创建使用已定义的GTT的存储过程。

答案 1 :(得分:3)

来自GTT documentation

  

创建全局临时表

     

是一个常规DDL语句,由引擎处理,与处理CREATE TABLE语句的方式相同。 因此,不是   可以在存储过程或触发器中创建或删除GTT。

您可以使用Dynamic-SQL并使用=IF(MOD(ROW()+1,2)=0,OFFSET(Sheet1!A$1,INT(ROW()/2),),"") 包装代码作为解决方法:

EXECUTE STATEMENT