目前我正在为应用程序设置测试环境。我在我的测试环境中使用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”... BEGIN ... FROM DUAL;)被执行成功,但如果我尝试使用它,触发器似乎已损坏。执行失败错误来自语句END的第二部分; “ORA-00900:无效的SQL语句”。
有人知道这个问题的解决方案吗?我只想用平台无关的瘦jdbc驱动程序创建一个触发器。
干杯!
凯文
答案 0 :(得分:2)
谢谢你们的回答,现在工作正常。原因是语法错误或使用Spring Framefork解释我的SQL代码文件。当我使用jdbc的execute方法直接执行语句时,它起作用,当我使用Spring功能执行脚本时,执行失败。使用oracle sql代码似乎很棘手,因为如果我使用hsqldb sql代码它可以正常工作。
测试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);
}
}
答案 1 :(得分:1)
创建触发器适用于任何类型的JDBC驱动程序; SQL语法一定有问题 - 这很奇怪,因为Oracle应该在运行CREATE TRIGGER
时报告(而不是在第一次使用它时)。
由于您使用BEGIN ... END;
,请确保在发送给数据库的SQL中;
之后确实有END
。
如果不是原因,check this article。
答案 2 :(得分:1)
我知道这是一个老帖子,但这是我的答案。
默认情况下,Spring“initialize-database”指令使用分号字符拆分指定的脚本:“;”。
在触发器中,触发器内部通常会有分号,因此查询会被严重分割并执行。
解决方案是使用另一个拆分字符(例如“|”),如下所示:
<jdbc:initialize-database>
<jdbc:script location="classpath:myscript.sql" separator="|"/>
</jdbc:initialize-database>