2016-08-10 4 views
0

ためschema.sqlで "DROP TABLE IF EXISTSを":使用することができません私は私のschema.sql内のテーブルの</p> <p>セットアップCREATE/DROPで助けを必要と春のブートアプリケーション

  • のOracle XEを
  • 春ブーツ1.4.0
  • のJava

私はschema.sqlに次のエントリを持っている1.8:

:私は、私は、Oracleに存在する場合にDROP TABLEを行う方法についていくつかの助けを見上げたときに例外

DROP TABLE table_a; nested exception is java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist 

は、私が得た最高の答えは、次の(のsqldeveloperで作品)だっ取得

DROP TABLE table_a; 

CREATE TABLE table_a 
(
    id      VARCHAR(5) PRIMARY KEY, 
    name      VARCHAR(100)); 

BEGIN 
    EXECUTE IMMEDIATE 'DROP TABLE table_a'; 
    EXCEPTION 
    WHEN OTHERS THEN 
    IF SQLCODE != -942 THEN 
    RAISE; 
    END IF; 

    EXECUTE IMMEDIATE 'CREATE TABLE table_a 
    (
    id    VARCHAR(5) PRIMARY KEY, 
    name    VARCHAR(100) 
)'; 
END; 

しかしながら、上記のコードは次の例外をスロー2016-08-10 14:55:36.232 INFO 9032 --- [main] osjdbc.datasource.init.ScriptUtils:URL [file:/ C:/ projects/project_a/target/classes/schemaからSQLスクリプトを実行しています。 [main] oswcsGenericWebApplicationContext:コンテキストの初期化中に例外が発生しました - リフレッシュの試みをキャンセルしました:org.springframework.beans.factory.BeanCreationException:名前が ' org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration ':autowired依存関係の注入に失敗しました。ネストされた例外はorg.springframework.beans.factory.BeanCreationExceptionです:フィールドをオートワイヤできませんでした:private javax.sql.DataSource org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.dataSource;ネストされた例外はorg.springframework.beans.factory.BeanCreationExceptionです:クラスパスのリソース[org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration $ NonEmbeddedConfiguration.class]で定義された 'dataSource'という名前のBeanを作成中にエラーが発生しました。ネストされた例外はorg.springframework.beans.factory.BeanCreationExceptionです: 'dataSourceInitializer'という名前のBeanを作成中にエラーが発生しました:initメソッドの呼び出しに失敗しました。ネストされた例外はorg.springframework.jdbc.datasource.init.ScriptStatementFailedExceptionです:URL [file:/ C:/projects/project_a/target/classes/schema.sql]のSQLスクリプトステートメント#1を実行するのに失敗しました:BEGIN EXECUTE IMMEDIATE 'DROP TABLE table_a ';ネストされた例外はjava.sql.SQLExceptionをある:ORA-06550:行1、列44: PLS-00103:記号 "エンドオブファイル" 以下のいずれかを期待するときに発生しました:

  • & = - +; < />はmodで残りはrem戻りません <>または!= or〜=> = < = <>および/または のような2のような4のような使い方||マルチセットバルク メンバーSUBMULTISET

は、誰もが春のブートでのOracleのテーブルのCREATE/DROPを処理するために、よりエレガントな方法がありますか?

+0

あなたが望むものはかなりわかりません。テーブルの作成は例外ハンドラ内にあります。テーブルが存在する場合、テーブルは削除され、再作成されません。とにかく、フレームワークは、最初のセミコロンまでの最初の2行をスタンドアロンの文として見ています。明らかに、すべてが1つのPL/SQLブロックであることはわかりません。文の区切り文字を変更できますか? –

+0

[oracle pl/sqlのテーブルの作成または置換]の可能な複製(http://stackoverflow.com/questions/16634699/create-or-replace-table-in-oracle-pl-sql) – mathguy

+1

@mathguy - 質問実際にはPL/SQLでテーブルを削除して作成する方法ではありません(ここではスキーマ作成スクリプトのようですが、実行時テーブル作成時の警告は実際には適用されません)。PL /春のブートからのSQLブロック? –

答えて

1

次に、あなたのschema.sqlは、SQL文を使用することができます

create or replace procedure recreate_table 
    (i_table_name in varchar2, i_create_stmt in varchar2) 
is 
BEGIN 
    BEGIN 
    EXECUTE IMMEDIATE 'DROP TABLE '||upper(i_table_name); 
    EXCEPTION 
    WHEN OTHERS THEN 
     IF SQLCODE != -942 THEN 
     RAISE; 
     END IF; 
    END; 
    EXECUTE IMMEDIATE i_create_stmt; 
END; 

ストアドプロシージャを作成します。

call recreate_table('TABLE_A','CREATE TABLE TABLE_A (ID NUMBER, VAL VARCHAR2(10))'); 

ではなく、PL/SQL

+0

これは働いた唯一のものです。 Spring-Bootでは、schema.sqlはPL/SQLを使用しません。 –

-5

これは本当にTSQLの質問だと思います。 tsql exist文を使用すると、システムテーブルを参照し、オブジェクトが存在するかどうかを確認できます。

+2

これはOracleの質問ですので、Microsoft SQL Serverの一部であるTSQLとは関係ありません。 –

1

表を削除して再作成するのではなく、グローバル一時表を使用することをお薦めします。グローバル・テンポラリ・テーブルの利点は、テーブルを作成し直して再作成する必要がないことです。

グローバルテンポラリテーブルについては、そのデータが作成されたセッションでのみ表示され、A)トランザクションがコミットするか、B)セッションが切断されたときにデータが自動的に削除されます。テーブルの作成時にデータを削除するタイミングを選択できますが、データは長期間保存されず、データベースに接続するすべての人には表示されません。これは、アプリケーションが一時的にテーブルにデータを入れ、特定のセッション内でそれを使用し、それを取り除く必要がある「スクラッチパッド」テーブルを対象としています。これがあなたの使用目的に合っていれば、これは良い方法です。あなたは次のように指定したいグローバルな一時テーブルとしてあなたのテーブルを作成するに

:。

CREATE GLOBAL TEMPORARY TABLE table_a 
    (id      VARCHAR(5) PRIMARY KEY, 
    name      VARCHAR(100)) 
    ON COMMIT PRESERVE ROWS; 

(と側のコメントなど - は、OracleとVARCHAR2の代わりにVARCHARを使用するのが習慣に取得する必要VARCHAR Oracle VARCHARは現在VARCHAR2の同義語ですが、Some Day OracleはVARCHARを変更して完全にANSI準拠になっているという噂があります。あなたのデータベースの動作は警告なしで静かに変化するかもしれません。これはあなたの警告です:-)。

幸運のベスト。

+0

実行されている 'schema.sql'スクリプトは*これは最初のスキーマの作成であり、その場合は防御的な削除は不合理ではないことを示唆しています。スクリプトが間違って1日コースに戻ってしまったのではないかと期待しなければなりません... GTTが関係しているかどうか分かりません。 –

+0

良いニュース - >上記のスクリプトが動作します。しかし、アプリケーションが終了した後、私はテーブルが落ちると予想しました。彼らが滞在しました。第二に、私は再びアプリケーションを実行したとき、私はそれらが上書きされると思った。ただし、例外が発生します。「ORA-00955:既存のオブジェクトによってすでに名前が使用されています」 –

+0

グローバル・テンポラリ・テーブルの利点は、一度作成するだけで、それが存在し続けることです。あなたはテーブルを何度も削除して再作成する必要はありません。 –

1

など、あなたのJavaのは示されていませんスタックトレースからは、デフォルトのセミコロンステートメントセパレータを使用したScriptUtil's executeSqlScript() methodが呼び出されているように見えます。

PL/SQLブロックを単一のユニットとして認識せず、最初のセミコロンまでのすべてをスタンドアロンSQL文として実行しようとしています。これは無効で、表示されているエラーが発生します。

あなたはデフォルトをオーバーライドし、代わりに/を使用することができますthe version of executeSqlScript()使用することができます。

public static void executeSqlScript(Connection connection, 
            EncodedResource resource, 
            boolean continueOnError, 
            boolean ignoreFailedDrops, 
            String commentPrefix, 
            String separator, 
            String blockCommentStartDelimiter, 
            String blockCommentEndDelimiter) 
          throws ScriptException 

セパレーター - スクリプトステートメントの区切りを、デフォルトは ";"指定されていなければ最後の手段として "\ n"に戻ります。スクリプトは、スクリプト内のすべてのSQL文が/、セパレータを使用する必要がありますを意味しますセパレーター

せずに単一の文が含まれていることを知らせるために「SCRIPT ^^^ ^^^ OF END」に設定することができます代わりに、あまりにもセミコロン:コメントで指摘したように

BEGIN 
    EXECUTE IMMEDIATE 'DROP TABLE table_a'; 
    EXCEPTION 
    WHEN OTHERS THEN 
    IF SQLCODE != -942 THEN 
    RAISE; 
    END IF; 
END; 
/

CREATE TABLE table_a 
    (
    id    VARCHAR(5) PRIMARY KEY, 
    name    VARCHAR(100) 
) 
/

... 

、元のブロックは、とにかく非常に適切ではありませんでした。 dropが必要な場合でも、createはPL/SQLによって実行する必要はありません。

しかし、その方法はまた、正確にあなたがやりたいように見える ignoreFailedDrops旗を持っている(私はかかわらず、チェックするために、それをテストすることはできません):

ignoreFailedDropsを - のイベントに継続するかどうか特にDROP文のエラー

そのバージョンを使用し、そのフラグにtrueを渡すと、ドロップの周りにPL/SQLラッパーは必要ありません。あなたはセミコロン区切りを維持してに戻すことができます:スキーマスクリプトは、他のPL/SQLが含まれている場合

DROP TABLE table_a; 

CREATE TABLE table_a 
(
    id      VARCHAR(5) PRIMARY KEY, 
    name      VARCHAR(100) 
); 

... 

- などのトリガー、パッケージ、 - そして、あなたはまだスラッシュ区切りの使用に切り替える必要がある(または任意のだろうあなたの選択の他のセパレータ;スラッシュはすべてのための伝統的ですが)です。

+0

その精巧な提案をありがとう。 Spring-Bootに上記のバージョンのexecuteSqlScript()メソッドを使用させる簡単な方法はありませんでした。だから、私はゲイリーマイヤーズが提供する以下の提案を使用しています。私は時間を得るとき、私はそれを動作させるために上記を使用する方法について調査します。 –

0

古いスレッドですが、私は最新のSpring Boot - 1.5.4で同じ問題を偶然見つけました。私は答えを見つけました(上記のAlex Pooleにも感謝します)。デフォルトでは、Springブートはプロパティを使用します。

spring.datasource.separator=; 

したがって、 ';'が表示されます。 SQLコマンドの区切り文字として使用されます。したがって、PL/SQLプロシージャを 'schema.sql'に入れようとする過程で、Oracle DBは最初のSQLコマンドのみを受け取り、DBに書き込もうとします。そう有するコード:

BEGIN 
    EXECUTE IMMEDIATE 'DROP TABLE table_a'; 
    EXCEPTION 
    WHEN OTHERS THEN 
    IF SQLCODE != -942 THEN 
    RAISE; 
    END IF; 
END; 

DBにおいては、BEGINとIMMEDIATE 'DROPテーブルtable_a' を実行します。保存されています - あなたはそれを例えば見ることができます。 SQL Developer。セパレータを例えばに変更する。 ';;'また、 ';'の代わりにSQLコードで使用することもできます。区切り記号として '/'を使用することはお勧めできません。これは、複数行のSQLコメントを作成するための記号であるため、誰かがSQLファイルでそれらを使用すると問題を引き起こす可能性があります。

関連する問題