Firebird 中过程自治事务语句中的表未知

问题描述 投票:0回答:1

我必须创建表并向其中插入数据。该操作并不意味着经常重复,但我们需要某种自动化。

我使用自治事务,但遇到同样的错误。根据发行说明

WITH AUTONOMOUS TRANSACTION 设置启动一个新事务 与 CURRENT_TRANSACTION 相同的参数。该交易将是 如果执行该语句则提交....

为什么会抛出异常(动态SQL错误。SQL错误代码 = -204。表未知。)?

CREATE OR ALTER PROCEDURE write_sh_record_with_clenup (
    tagid TYPE OF COLUMN "SNAPSHOT".tagid,
    scannername VCHAR30_REQ)
AS
  DECLARE VARIABLE tablename TABLE_NAME;
  DECLARE PROCEDURE create_sh_table (name TABLE_NAME)
  AS
  BEGIN
    EXECUTE STATEMENT 'CREATE TABLE "' || :name || '" (tagid TAG_ID, dateyear DATE_PART, dayofyear DATE_PART, totalseconds SECONDS_TIMESTAMP, "VALUE" DOUBLE PRECISION);'
    WITH AUTONOMOUS TRANSACTION;
    WHEN ANY DO
    BEGIN
      EXCEPTION ex_custom USING (UPPER('create_sh_table'), GDSCODE, SQLCODE, SQLSTATE);
    END
  END
BEGIN
  :tablename = 'SH_' || :scannername;
  IF (get_table_exists(:tablename) = 'F') THEN
    EXECUTE PROCEDURE create_sh_table(:tablename);
  EXECUTE STATEMENT 'INSERT INTO ' || :tablename || ' SELECT * FROM snapshot WHERE tagid = ' || :tagid || ';';
END
stored-procedures firebird firebird-psql firebird-4.0
1个回答
0
投票

如果您使用隔离级别 SNAPSHOT 或 SNAPSHOT TABLE STABILITY 运行此程序,这完全是预期的:您的过程只能看到在其事务开始之前提交的其他事务的状态。如果您使用的是 READ COMMITTED,这也是预期行为 since Firebird 4.0。

Firebird 4.0 引入了一种处理 READ COMMITTED 事务的新方法,读已提交读一致性,并且这是默认启用的。使用这种读已提交模式,语句将看到已提交事务在语句启动之前的状态。对于存储过程,该语句是直接或间接调用该过程的 DSQL selectexecute procedure

因此,即使您在自治事务中创建了表,并且该事务已提交,但就外部过程而言,它并不存在,因为该事务是在事务启动后
提交的。

真正的解决方案是不要像这样动态创建表,但是,您还有两种解决方法:

在 firebird.conf 中禁用设置

ReadConsistency

,将其设置为
    0
  1. 而不是默认的

    1

    ,并确保您的事务以 
    READ COMMITTED RECORD_VERSION
    READ COMMITTED NO RECORD_VERSION
    (而不是 
    READ COMMITTED READ CONSISTENCY
    )启动).
    我不推荐这个选项,这是一个过渡配置,最终会消失:不要依赖它。

    也使用自主事务执行插入。如果您不需要看到当前事务中未提交的更改,这只是一个可行的解决方法。

© www.soinside.com 2019 - 2024. All rights reserved.