简体   繁体   中英

ORA-06550 line 2, column 44:PLS-00103: Encountered the symbol "end-of-file"

I am trying to execute a SQL script from Java using some rxjava2 methods. I have a resource file called init_db.sql .

Its content:

BEGIN
EXECUTE IMMEDIATE 'DROP TABLE animals';
EXCEPTION
   WHEN OTHERS THEN
      IF SQLCODE != -942 THEN
         RAISE;
      END IF;
END;
/
CREATE TABLE animals (
  id        NUMBER GENERATED ALWAYS as IDENTITY(START with 1 INCREMENT by 1),
  name      VARCHAR2(40) NOT NULL,
  amount    INT,
  CONSTRAINT animals_pk PRIMARY KEY (id));

INSERT INTO animals (name, amount) values ('Cats', 10);
INSERT INTO animals (name, amount) values ('Dogs', 10);
INSERT INTO animals (name, amount) values ('Rats', 10);

The method where the Java code is executed is the next:

public  Completable initOracleDatabase(Vertx vertx, JDBCClient jdbc) {
    System.out.println("Init Oracle Database **** executing..sql script...");
    Completable completable =
      jdbc.rxGetConnection().flatMapCompletable(sqlConnection -> vertx.fileSystem().rxReadFile("init_db.sql")
        .flatMapObservable(buffer -> Observable.fromArray(buffer.toString().replaceAll(";.*$", "").split(";")))
        .flatMapCompletable(sqlConnection::rxExecute)
        .doAfterTerminate(sqlConnection::close));
   
    return completable;

And this is the error that I got from the logs:

java.sql.SQLException: ORA-06550: line 2, column 44:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
 * & = - + ; < / > at in is mod remainder not rem return
returning <an exponent (**)> <> or != or ~= >= <= <> and or
 like like2 like4 likec between into using || multiset bulk
 member submultiset

and the error trace log:

at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:509)
  at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:461)
  at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1104)
  at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:553)
  at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:269)
  at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:655)
  at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:229)
  at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:41)
  at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:928)
  at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1205)
  at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1823)
  at oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1778)
  at oracle.jdbc.driver.OracleStatementWrapper.execute(OracleStatementWrapper.java:303)

Basically I would like to know if can I use in one only statement this SQL scriptor not? or if I am missing anything or some error code translate between SQL script and Java?

You are mixing PL/SQL and SQL code in the same script.

  • SQL statements can be terminated by ; .
  • PL/SQL blocks are terminated by / on a newline and will contain nested PL/SQL (or SQL) statements that are each terminated by ; .

So you cannot naively split your code on ; and expect it to work as you will incorrectly split the PL/SQL blocks.

In addition to using ; as an SQL statement terminator, you can also use / on a newline; so you could rewrite your script as:

BEGIN
  EXECUTE IMMEDIATE 'DROP TABLE animals';
EXCEPTION
  WHEN OTHERS THEN
    IF SQLCODE != -942 THEN
      RAISE;
    END IF;
END;
/

CREATE TABLE animals (
  id        NUMBER GENERATED ALWAYS as IDENTITY(START with 1 INCREMENT by 1),
  name      VARCHAR2(40) NOT NULL,
  amount    INT,
  CONSTRAINT animals_pk PRIMARY KEY (id)
)
/

INSERT INTO animals (name, amount) values ('Cats', 10)
/
INSERT INTO animals (name, amount) values ('Dogs', 10)
/
INSERT INTO animals (name, amount) values ('Rats', 10)
/

And split the script on \n/\n .

Or, you can just ignore catching the ORA-00942 exception and just use SQL and continue using the ; statement terminator:

DROP TABLE animals;

CREATE TABLE animals (
  id        NUMBER GENERATED ALWAYS as IDENTITY(START with 1 INCREMENT by 1),
  name      VARCHAR2(40) NOT NULL,
  amount    INT,
  CONSTRAINT animals_pk PRIMARY KEY (id)
);

INSERT INTO animals (name, amount) values ('Cats', 10);
INSERT INTO animals (name, amount) values ('Dogs', 10);
INSERT INTO animals (name, amount) values ('Rats', 10);

Or, you can create a more complicated solution that actually parses PL/SQL and SQL statements and can split the script into individual statement based on the syntax tree.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM