4

現在、アプリケーションのテスト環境をセットアップしています。テスト環境でjUnitとSpringを使用しています。テストを実行する前に、データベースのテスト環境の状態を設定したいと思います。私はすでにSQLスクリプト(スキーマとデータ)を作成しており、それらはOraclesSQLDeveloperで正常に実行されます。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の2番目の部分にあります。「ORA-00900:無効なSQLステートメント」。

誰かがその問題の解決策を知っていますか?プラットフォームに依存しないシンjdbcドライバーでトリガーを作成したいだけです。

乾杯!

ケビン

4

3 に答える 3

2

皆さん、ご回答ありがとうございます。現在は正常に動作しています。その理由は、構文の誤りか、Spring Framefork での SQL コード ファイルの解釈でした。jdbc の execute メソッドを使用してステートメントを直接実行すると機能しますが、スクリプトの実行に Spring 機能を使用すると実行が失敗します。hsqldb sql コードを使用すると正常に動作するため、oracle 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>
...

スキーマ.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(最初に使用したときではなく) を実行したときに報告するはずだからです。

使用するので、DB に送信する SQL にBEGIN ... END;本当に;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 に答える