PLS-00103: 在 FlyWay 中遇到符号 "end-of-file"

PLS-00103: Encountered the symbol "end-of-file" in FlyWay

我们有一个数据库迁移脚本,它是 运行 通过 FlyWay 的,它是 Java 应用程序的一部分。问题是一些客户使用旧版本的应用程序,其中显示了一些 table 和数据,而其他客户将安装此产品作为新解决方案。这些脚本每次都必须 运行(解决方案问题和历史问题)。

事实上,我们在 SQL 中通过简单检查来处理这个问题,如果 table 存在,然后执行脚本的其余部分。它适用于其他数据库(Postgres、MySQL、MS SQL)但不适用于 Oracle。经过几天的尝试和谷歌搜索,我开始把头发从头上扯下来。第一个问题是执行 DDL 语句(我已经知道我不能那样做)现在是这个。

我们训练的目标是什么:

  1. 运行 脚本如果 main table 存在于当前用户(这就是我们的方式 确定,如果所有其他 table 也存在)
  2. 对于每个 table 我们需要创建一个备份 table 并复制其中的所有行(这就是我们执行 TRUNCATE 和 INSERT INTO 的原因,如果失败, 我们做 CREATE TABLE AS) - 这是呈现的代码应该做的,IF table_count > 0 THEN 和 END IF 内的代码块;每出现一次 table 重复一次 (11x)
  3. 然后我们 运行 清理脚本,它检查坏数据并清理它们(我们必须存储原始值以防万一 变坏了)。
  4. 清理后的数据被复制到新的 table 中(在之前的脚本中准备)。

总共有10个脚本,但是这个一直在失败。

代码如下:

DECLARE 
  table_count NUMBER;
  curr_user VARCHAR2(100);  
BEGIN
  SELECT
  sys_context('USERENV','SESSION_USER') INTO curr_user 
  FROM dual;

  SELECT count(*)
  INTO table_count
  FROM all_objects
  WHERE object_type IN ('TABLE', 'VIEW')
  AND object_name = 'main_table'
  AND owner = curr_user;

  IF table_count > 0 THEN
    BEGIN
      EXECUTE IMMEDIATE 'TRUNCATE TABLE some_table_backup';
      EXECUTE IMMEDIATE 'INSERT INTO some_table_backup
          SELECT *
          FROM some_table';
      EXCEPTION
      WHEN OTHERS THEN
      IF SQLCODE != -942
      THEN
        RAISE;
      ELSE
        EXECUTE IMMEDIATE 'CREATE TABLE some_table_backup AS SELECT * FROM some_table';
      END IF;
    END;

    BEGIN
      EXECUTE IMMEDIATE 'TRUNCATE TABLE some_table_backup2';
      EXECUTE IMMEDIATE 'INSERT INTO some_table_backup2
          SELECT *
          FROM some_table2';
      EXCEPTION
      WHEN OTHERS THEN
      IF SQLCODE != -942
      THEN
        RAISE;
      ELSE
        EXECUTE IMMEDIATE 'CREATE TABLE some_table_backup2 AS SELECT * FROM some_table2';
      END IF;
    END;   
.
.
.

  END IF;

EXCEPTION
  WHEN OTHERS
  THEN
  DBMS_OUTPUT.put_line(SQLERRM);
END;

错误如下:

ORA-06550: line 30, column 8:

PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:

第30行结束;在 END IF 之后;在脚本的第一个分区中。

您的 FlyWay 版本似乎不喜欢嵌套的 PL/SQL 块。我会尝试添加匿名块标签:

DECLARE 
  table_count NUMBER;
  curr_user VARCHAR2(100);  
BEGIN
  SELECT
  sys_context('USERENV','SESSION_USER') INTO curr_user 
  FROM dual;

  SELECT count(*)
  INTO table_count
  FROM all_objects
  WHERE object_type IN ('TABLE', 'VIEW')
  AND object_name = UPPER('main_table')    --here I added UPPER
  AND owner = curr_user;

  IF table_count > 0 THEN
    <<name1>>
    BEGIN
      EXECUTE IMMEDIATE 'TRUNCATE TABLE some_table_backup';
      EXECUTE IMMEDIATE 'INSERT INTO some_table_backup
          SELECT *
          FROM some_table';
      EXCEPTION
      WHEN OTHERS THEN
      IF SQLCODE != -942
      THEN
        RAISE;
      ELSE
        EXECUTE IMMEDIATE 'CREATE TABLE some_table_backup AS SELECT * FROM some_table';
      END IF;
    END name1;

    <<name2>>
    BEGIN
      EXECUTE IMMEDIATE 'TRUNCATE TABLE some_table_backup2';
      EXECUTE IMMEDIATE 'INSERT INTO some_table_backup2
          SELECT *
          FROM some_table2';
      EXCEPTION
      WHEN OTHERS THEN
      IF SQLCODE != -942
      THEN
        RAISE;
      ELSE
        EXECUTE IMMEDIATE 'CREATE TABLE some_table_backup2 AS SELECT * FROM some_table2';
      END IF;
    END name2;   


  END IF;

EXCEPTION
  WHEN OTHERS
  THEN
  DBMS_OUTPUT.put_line(SQLERRM);
END;
/

或者,您可以通过改变方法来避免嵌套 PL/SQL 块。

您可以轻松地检查 table 是否存在,然后执行操作,而不是先尝试做某事并处理异常。这样就根本不需要嵌套 PL/SQL 块。

第二种选择是使用动态 SQL:

DECLARE 
  table_count NUMBER;
  curr_user VARCHAR2(100);  
BEGIN
  SELECT
  sys_context('USERENV','SESSION_USER') INTO curr_user 
  FROM dual;

  SELECT count(*)
  INTO table_count
  FROM all_objects
  WHERE object_type IN ('TABLE', 'VIEW')
  AND object_name = UPPER('main_table')
  AND owner = curr_user;

  IF table_count > 0 THEN

    EXECUTE IMMEDIATE q'{
    BEGIN
      EXECUTE IMMEDIATE 'TRUNCATE TABLE some_table_backup';
      EXECUTE IMMEDIATE 'INSERT INTO some_table_backup
          SELECT *
          FROM some_table';
      EXCEPTION
      WHEN OTHERS THEN
      IF SQLCODE != -942
      THEN
        RAISE;
      ELSE
        EXECUTE IMMEDIATE 'CREATE TABLE some_table_backup AS SELECT * FROM some_table';
      END IF;
    END;}';

    EXECUTE IMMEDIATE q'{
    BEGIN
      EXECUTE IMMEDIATE 'TRUNCATE TABLE some_table_backup2';
      EXECUTE IMMEDIATE 'INSERT INTO some_table_backup2
          SELECT *
          FROM some_table2';
      EXCEPTION
      WHEN OTHERS THEN
      IF SQLCODE != -942
      THEN
        RAISE;
      ELSE
        EXECUTE IMMEDIATE 'CREATE TABLE some_table_backup2 AS SELECT * FROM some_table2';
      END IF;
    END;}';   

  END IF;

EXCEPTION
  WHEN OTHERS
  THEN
  DBMS_OUTPUT.put_line(SQLERRM);
END;

请注意 q'{}' 文本文字的用法,它允许处理 ' 而无需复制它们。

使用 FlyWay 4.2.0(从命令行调用)两个示例都可以正常工作。