目前,我为应用程序设置了测试环境。我在测试环境中使用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>
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top