![](/img/trans.png)
[英]SQLSyntaxErrorException: ORA-00900: invalid SQL statement using Java
[英]Running Oracle sql script from java gives SQLSyntaxErrorException: ORA-00900: invalid SQL statement
我使用的是Oracle 11g,我正在通过java代码执行Oracle sql脚本。 我的SQL脚本可能包含SQL语句(DDL或DML)或PL / SQL块,因此我不想在我的java代码中解析脚本,而是使用此解决方案立即执行完整脚本。 以下是示例代码,其中SQLExec类位于ant jar
。
此解决方案适用于大多数情况,但如果sql脚本包含create or replace trigger
则会因java.sql.SQLSyntaxErrorException而失败:ORA-00900:无效的SQL语句 。 我还指定了失败的sql脚本片段。
请注意,如果我通过SQL Developer运行相同的脚本,它运行正常。
以下是Java代码:
private void executeSql(String sqlFilePath) {
final class SqlExecuter extends SQLExec {
public SqlExecuter() {
Project project = new Project();
project.init();
setProject(project);
setTaskType("sql");
setTaskName("sql");
}
}
SqlExecuter executer = new SqlExecuter();
executer.setSrc(new File(sqlFilePath));
executer.setDriver(args.getDriver());
executer.setPassword(args.getPwd());
executer.setUserid(args.getUser());
executer.setUrl(args.getUrl());
executer.execute();
}
SQL脚本片段:
......
......
CREATE OR REPLACE TRIGGER MY_TRG
BEFORE INSERT ON MY_TABLE
FOR EACH ROW
BEGIN
:NEW.MYNUMBER := MY_SEQUENCENUM.NEXTVAL;
END;
以下是异常跟踪:
Exception in thread "main" java.sql.SQLSyntaxErrorException: ORA-00900: invalid SQL statement
at org.apache.tools.ant.taskdefs.SQLExec.execute(SQLExec.java:398)
at com.kuldeep.OracleConnectionTest.executeSql(OracleConnectionTest.java:160)
at com.kuldeep.OracleConnectionTest.main(OracleConnectionTest.java:25)
Caused by: java.sql.SQLSyntaxErrorException: ORA-00900: invalid SQL statement
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:194)
at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:1000)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1307)
at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1882)
at oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1847)
at oracle.jdbc.driver.OracleStatementWrapper.execute(OracleStatementWrapper.java:301)
at org.apache.tools.ant.taskdefs.SQLExec.execSQL(SQLExec.java:499)
at org.apache.tools.ant.taskdefs.SQLExec.runStatements(SQLExec.java:470)
at org.apache.tools.ant.taskdefs.SQLExec$Transaction.runTransaction(SQLExec.java:664)
at org.apache.tools.ant.taskdefs.SQLExec$Transaction.access$000(SQLExec.java:627)
at org.apache.tools.ant.taskdefs.SQLExec.execute(SQLExec.java:370)
在文档中它说:
可以提供多个语句,以分号(或定义的分隔符)分隔。
因此,使用分号字符(;)作为默认分隔符, SQLEXEC
将脚本的CREATE TRIGGER
语句解释为两个语句,并将此错误消息作为结果。
正如@Reza Goodarzi所提到的无效SQL语句的原因是分号被用作语句分隔符。 所以为了解决我的问题,我用slash(/)
作为分隔符分隔每个语句,并遵循我自己创建的这些规则:
每个SQL语句(不是PL / SQL块的一部分)和PL / SQL块必须以新行中的转发斜杠(/)结尾。
SQL语句(不是PL / SQL块的一部分)不应以分号( ; )结尾。 我刚刚从语句末尾删除了分号。
对于PL / SQL块,不要从块的末尾以及块中包含的任何语句中删除分号( ; )。
通过在我的SQL脚本中进行这些更改,我通过自己解析文件而不是使用SQLExec或任何其他外部API,一次执行(使用jdbc)每个PL / SQL块和每个SQL语句(不是PL / SQL块的一部分) /图书馆。
我认为您需要更改触发器以设置新ID
create or replace trigger MY_TRG
BEFORE insert MY_TABLE
for each row
begin
if (:new.MYNUMBER is null) then
select MY_SEQUENCENUM.nextval
into :new.MYNUMBER
from DUAL;
end if;
end;
/
或这个:
create or replace trigger TG_BIU_TABLE1
before insert or update on TABLE1
for each row
begin
if (:new.ID1 is null) then
select SQ_TABLE1.nextval
into :new.ID1
from DUAL
end if
end
/
您还可以在execute语句中添加分隔符,如下所示:
......
......
DELIMITER $$
CREATE OR REPLACE TRIGGER MY_TRG
BEFORE INSERT ON MY_TABLE
FOR EACH ROW
BEGIN
:NEW.MYNUMBER := MY_SEQUENCENUM.NEXTVAL;
END; $$
......
我还将脚本的最后一部分留给触发器和过程,因为分隔符是向前使用的。 这对我有用。 由SQL Developer的Migration工具提供。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.