简体   繁体   English

PLS-00103:在FlyWay中遇到符号“文件结尾”

[英]PLS-00103: Encountered the symbol “end-of-file” in FlyWay

We have a database migration scripts, which are run trough FlyWay, which is part of Java app. 我们有一个数据库迁移脚本,该脚本通过FlyWay运行,它是Java应用程序的一部分。 The problem is that some customers have the older version of app, where some table and data are presented, while others will be installing this product as new solution. 问题在于某些客户使用的应用程序版本较旧,其中显示了一些表和数据,而另一些客户将安装此产品作为新解决方案。 These scripts must run everytime (solution problem and historical problem). 这些脚本必须每次都运行(解决问题和历史问题)。

In fact, we handle this in SQL with simple check, if table exist and then execute the rest of script. 实际上,我们通过简单的检查在SQL中进行处理(如果表存在),然后执行其余脚本。 It works quite fine for other databases (Postgres, MySQL, MS SQL) but not for Oracle. 对于其他数据库(Postgres,MySQL,MS SQL),它工作得很好,但对于Oracle,则不能。 And after few days of trying and googling I am starting to rip my hair off of my head. 经过几天的尝试和谷歌搜索,我开始把头发从头上扯下来。 First problem was executing DDL statements (already learned I can't do that) and now this. 第一个问题是执行DDL语句(已经知道我做不到),而现在是这样。

What are we traing to achieve: 我们要实现的目标是:

  1. Run script if main table exists for current user (that's how we determine, if all other table exists too) 如果当前用户存在主表,则运行脚本(这就是我们确定所有其他表是否也存在的方式)
  2. For every table we need to create a backup table and copy all rows in it (thats why we do TRUNCATE and INSERT INTO and if fails, we do CREATE TABLE AS) - this is what presented code should do, block of code inside IF table_count > 0 THEN and END IF; 对于每个表,我们需要创建一个备份表并复制其中的所有行(这就是为什么我们执行TRUNCATE和INSERT INTO的原因,如果失败,我们将创建CREATE TABLE AS) -这就是所呈现的代码应该执行的操作,即在IF table_count中的代码块> 0 THEN和END IF; is repeated per every table presented (11x) 每个显示的表重复一次(11x)
  3. We then run the cleanup script, which checks for bad data and clean them (we must have original values stored in case something goes bad). 然后,我们运行清除脚本,该脚本检查不良数据并清除它们(必须存储原始值,以防某些情况变坏)。
  4. Cleaned datas are copied into new tables (prepared in previous script). 清理后的数据将复制到新表中(在上一个脚本中准备)。

There is 10 scripts in total, but this one is constantly failing. 总共有10个脚本,但是这个脚本一直在失败。

Here is the code: 这是代码:

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;

The error is following: 错误如下:

ORA-06550: line 30, column 8: ORA-06550:第30行,第8列:

PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: PLS-00103:预期以下情况之一时遇到符号“文件结束”:

Line 30 is END; 第30行是END; after END IF; 在END IF之后; in first partition of script. 在脚本的第一个分区中。

It looks like that your version of FlyWay does not like nested PL/SQL Blocks. 看来您的FlyWay版本不喜欢嵌套的PL / SQL块。 I would try to add anonymous block labels: 我会尝试添加匿名块标签:

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;
/

Alternatively you could avoid nested PL/SQL block by changing approach. 另外,您可以通过更改方法来避免嵌套的PL / SQL块。

Instead of trying to do something first and handle exception, you could easily check if table exist or not and then do the action. 您可以轻松地检查表是否存在,然后执行操作,而不是先尝试做一些事情并处理异常。 That way there is no need for nested PL/SQL blocks at all. 这样,根本就不需要嵌套的PL / SQL块。

Second alternative is to use dynamic 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;

Please note the usage of q'{}' text literal that allow to handle ' without duplicating them. 请注意q'{}'文本文字的用法,该文本常量可以处理'而无需复制它们。

With FlyWay 4.2.0(called from command-line) both samples work as it should. 使用FlyWay 4.2.0(从命令行调用)时,两个示例都可以正常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 PLS-00103:遇到符号“文件结束” - PLS-00103: Encountered the symbol “end-of-file” ORA-06550 第 2 行,第 44 列:PLS-00103: 遇到符号“文件结束” - ORA-06550 line 2, column 44:PLS-00103: Encountered the symbol "end-of-file" PLS-00103:预期以下情况之一时遇到符号“ TEST_PKG”: - PLS-00103: Encountered the symbol “TEST_PKG” when expecting one of the following: ; 错误:PLS-00103:在预期以下情况之一时遇到符号“ AS”:返回 - Error: PLS-00103: Encountered the symbol “AS” when expecting one of the following:return BufferedReader 中的 GZIPInputStream 文件结尾序列 - GZIPInputStream end-of-file sequence in BufferedReader 如何读取二进制文件直到文件结束? - How to read binary file until the end-of-file? 合并文件给出错误:文件结束,预期行 - merge files gives error: End-of-File, expected line 在 Eclipse 下运行时,BufferedReader 在 StdIn 上看不到文件结尾 - BufferedReader not seeing end-of-file on StdIn when run under Eclipse 使用 Java 的 Scanner 类确定文件结尾 - Determine end-of-file using Java's Scanner class java.io.IOException:错误:文件结束,预期行 PDFBox 问题 - java.io.IOException: Error: End-of-File, expected line Issue with PDFBox
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM