4

目前我为应用程序设置了一个测试环境。我在我的测试环境中使用 jUnit 和 Spring。在测试执行之前,我想设置一个数据库测试环境状态。我已经编写了 SQL 脚本(模式和数据),它们在 Oracle SQLDeveloper 中运行良好。当我尝试使用 oracle 瘦 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 驱动程序创建一个触发器。

干杯!

凯文

4

3 回答 3

2

谢谢大家的回答,现在可以正常使用了。原因是语法错误或使用 Spring Framefork 对我的 SQL 代码文件的解释。当我使用 jdbc 的 execute 方法直接执行语句时,它可以工作,当我使用 Spring 功能执行脚本时,执行失败。使用 oracle sql 代码似乎很棘手,因为如果我使用 hsqldb sql 代码它可以正常工作。

测试条件.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>
...

架构.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);
    }
}
于 2010-11-06T12:15:48.800 回答
1

创建触发器适用于任何类型的 JDBC 驱动程序;SQL 语法一定有问题——这很奇怪,因为 Oracle 应该在您运行时报告CREATE TRIGGER(而不是在您第一次使用它时)。

由于您使用BEGIN ... END;确保您在发送到数据库的 SQL 中确实有一个;after 。END

如果这不是原因,请查看这篇文章

于 2010-11-05T15:00:28.323 回答
1

我知道这是一篇旧帖子,但这是我的答案。

默认情况下,Spring“initialize-database”指令使用分号字符:“;”分割指定的脚本。

在触发器中,触发器内部通常有一个分号,因此查询被严重拆分和执行。

解决方案是使用另一个拆分字符(例如“|”),如下所示:

<jdbc:initialize-database>
    <jdbc:script location="classpath:myscript.sql" separator="|"/>
</jdbc:initialize-database>
于 2013-04-10T11:27:30.070 回答