使用薄JDBC驱动程序创建Oracle DB触发器
题
目前,我为应用程序设置了测试环境。我在测试环境中使用Junit和Spring。在测试执行之前,我想设置数据库测试环境状态。我已经编写了SQL脚本(架构和数据),它们在Oracles Sqldeveloper中运行良好。当我尝试使用Oracle Thin JDBC驱动程序执行它们时,执行失败。看起来薄驱动程序不喜欢创建触发语句。
我读到我必须使用OCI驱动程序而不是薄驱动程序。 OCI驱动程序的问题在于它不是独立的平台,并且需要时间进行设置。
我的代码的示例:
CREATE TABLE "USER"
(
USER_ID NUMBER(10) NOT NULL,
CREATOR_USER_FK NUMBER(10) NOT NULL,
...
PRIMARY KEY (USER_ID)
);
CREATE SEQUENCE SEQ_USER START WITH 1 INCREMENT BY 1;
CREATE TRIGGER "USER_ID_SEQ_INC" BEFORE
INSERT ON "USER" FOR EACH ROW BEGIN
SELECT SEQ_USER.nextval
INTO :new.USER_ID
FROM DUAL;
END;
如果我执行触发器语句,则执行失败,但是我看起来像查询的第一部分(Create Trigger“ user_id_seq_inc” ...“ user” ...“ user” ...从dual; dual;)成功执行,但是如果我尝试使用它,扳机似乎会损坏。执行失败错误与语句结束的第二部分有关; “ ORA-00900:无效的SQL语句”。
有人知道解决这个问题的解决方案吗?我只想创建一个使用平台独立的薄JDBC驱动程序来创建一个触发器。
干杯!
凯文
解决方案
谢谢你们的回答,现在可以正常工作。原因是语法错误或使用Spring Framefork对我的SQL代码文件的解释。当我使用JDBC的执行方法直接执行语句时,当我使用Spring功能执行脚本执行时,执行失败。使用Oracle SQL代码似乎很棘手,因为如果我使用HSQLDB SQL代码,则可以正常工作。
test-condext.xml:
...
<jdbc:initialize-database data-source="dataSource"
ignore-failures="DROPS" enabled="${jdbc.enableSqlScripts}">
<jdbc:script location="${jdbc.initLocation}" />
<jdbc:script location="${jdbc.dataLocation}" />
</jdbc:initialize-database>
...
schema.sql:
DROP SEQUENCE SEQ_USER;
DROP TABLE "USER" CASCADE CONSTRAINTS;
PURGE TABLE "USER";
CREATE TABLE "USER"
(
USER_ID NUMBER(10) NOT NULL,
CREATOR_USER_FK NUMBER(10) NOT NULL,
PRIMARY KEY (USER_ID)
);
ALTER TABLE "USER" ADD CONSTRAINT FK_USER_CUSER FOREIGN KEY (CREATOR_USER_FK) REFERENCES "USER" (USER_ID);
CREATE SEQUENCE SEQ_USER START WITH 1 INCREMENT BY 1;
CREATE TRIGGER "USER_ID_SEQ_INC" BEFORE
INSERT ON "USER" FOR EACH ROW
WHEN (new.USER_ID IS NULL)
BEGIN
SELECT SEQ_USER.nextval
INTO :new.USER_ID
FROM DUAL;
END;
/
ALTER TRIGGER "USER_ID_SEQ_INC" ENABLE;
这很好!去除很重要 ;
在语句的结尾,触发语句除外!!!
@Before
public void executeSomeSql() {
Connection c;
try {
c = dataSource.getConnection();
c.createStatement()
.execute("CREATE TABLE \"USER\" (USER_ID NUMBER(10) NOT NULL, CREATOR_USER_FK NUMBER(10) NOT NULL, PRIMARY KEY (USER_ID))");
c.createStatement()
.execute("CREATE SEQUENCE SEQ_USER START WITH 1 INCREMENT BY 1");
c.createStatement()
.execute("CREATE OR REPLACE TRIGGER \"USER_ID_SEQ_INC\" BEFORE INSERT ON \"USER\" FOR EACH ROW WHEN (new.USER_ID IS NULL) BEGIN SELECT SEQ_USER.nextval INTO :new.USER_ID FROM DUAL; END;");
} catch (SQLException e) {
logger.debug(e);
}
}
其他提示
创建触发器可与任何类型的JDBC驱动程序一起使用; SQL语法一定有问题 - 这很奇怪,因为Oracle应该报告运行时 CREATE TRIGGER
(不是第一次使用时)。
因为您使用 BEGIN ... END;
确保您真的有一个 ;
后 END
在您发送到DB的SQL中。
如果那不是原因, 检查本文.
我知道这是一个古老的帖子,但这是我的答案。
默认情况下,Spring“ Initialize-Database”指令使用Semicolon字符分开指定的脚本:”;“。
在触发器中,触发器内通常有一个半龙,因此查询被严重拆分和执行。
解决方案是使用其他拆分字符(例如“ |”):
<jdbc:initialize-database>
<jdbc:script location="classpath:myscript.sql" separator="|"/>
</jdbc:initialize-database>