PLS-00103:在FlyWay

时间:2017-10-30 15:01:11

标签: java oracle flyway

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

事实上,我们通过简单检查在SQL中处理这个问题,如果表存在则执行其余的脚本。它适用于其他数据库(Postgres,MySQL,MS SQL),但不适用于Oracle。经过几天的尝试和谷歌搜索,我开始撕掉我的头发。第一个问题是执行DDL语句(已经学会了我不能这样做),现在就这样了。

我们要实现什么目标:

  1. 如果当前用户存在主表,则运行脚本(这就是我们的方式 确定,如果所有其他表也存在)
  2. 对于每个表,我们需要创建一个备份表并复制其中的所有行(这就是为什么我们执行TRUNCATE和INSERT INTO,如果失败, 我们做CREATE TABLE AS) - 这是代码应该做的,IF table_count中的代码块> 0 THEN和END IF;每个呈现的表格重复(11x)
  3. 然后我们运行清理脚本,检查坏数据并清理它们(我们必须保存原始值,以防万一 变坏了。
  4. 已清理的数据将复制到新表中(在以前的脚本中准备)。
  5. 总共有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:第30行,第8栏:

         

    PLS-00103:遇到以下任何一种情况时遇到符号“文件结束”:

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

1 个答案:

答案 0 :(得分:2)

看起来您的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块。

您可以轻松检查表是否存在,而不是尝试先做某事并处理异常,然后再执行操作。这样就根本不需要嵌套的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(从命令行调用),两个示例都可以正常工作。