使用瘦 jdbc 驱动程序创建 Oracle 数据库触发器

发布于 2024-09-30 15:16:02 字数 893 浏览 1 评论 0原文

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

干杯!

凯文

currently I setting up a test environment for an application. I'm using jUnit and Spring in my test environment. Before a test execution I want to set up a database test environment state. I already has written the SQL scripts (schema and data) and they runs fine in Oracles SQLDeveloper. As I tried to execute them by using the oracle thin jdbc driver, the execution fails. It looks like that the thin driver doesn't like create trigger statements.

I read that I have to use an oci driver instead of thin driver. The problem with the oci driver is that it is not platform independent and it takes time to set it up.

Example of my code:

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;

If I execute the the trigger statement the execution fails, but I looks like that the first part of the query (CREATE TRIGGER "USER_ID_SEQ_INC" ... "USER" ... BEGIN ... FROM DUAL;) is executed successfully, but the trigger seems to be corrupt if I try to use it. The execution fail error comes with the second part of the statement END; "ORA-00900: invalid SQL statement".

Do anyone know a solution for that problem? I just want to create a trigger with platform independent thin jdbc driver.

Cheers!

Kevin

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

日暮斜阳 2024-10-07 15:16:02

谢谢各位的解答,现在已经可以正常使用了。原因是语法错误或使用 Spring Framefork 对 SQL 代码文件的解释。当我使用jdbc的execute方法直接执行语句时,它可以工作,当我使用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);
    }
}

Thank you guys for your answers, It works fine now. The reason was a syntax mistake or the interpretation of my SQL code file with Spring Framefork. When I execute the statements directly by using the execute method of jdbc it works, when I use the Spring functionality for script execution the execution fails. With oracle sql code it seems to be tricky, because if I use hsqldb sql code it works fine.

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;

This works fine! Its important to remove ; at the end of statements excepts the trigger statement!!!

@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);
    }
}
玩物 2024-10-07 15:16:02

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

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

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

Creating triggers works with any type of JDBC driver; there must be something wrong with the SQL syntax -- which is odd because Oracle should report that when you run the CREATE TRIGGER (not when you use it the first time).

Since you use BEGIN ... END; make sure that you really have a ; after END in the SQL which you send to the DB.

If that isn't the cause, check this article.

迷你仙 2024-10-07 15:16:02

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

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

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

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

<jdbc:initialize-database>
    <jdbc:script location="classpath:myscript.sql" separator="|"/>
</jdbc:initialize-database>

I know this is a old post but here's my answer.

By default, Spring "initialize-database" instruction split the specified script by using the semicolon character : ";".

In a trigger, there often is a semicolon inside the trigger, thus the queries are badly splitted and executed.

The solution is to use another split character ("|" for example) like this :

<jdbc:initialize-database>
    <jdbc:script location="classpath:myscript.sql" separator="|"/>
</jdbc:initialize-database>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文