コメンターが指摘したように、コードが期待どおりに機能しない理由はいくつかあります。
まず、に渡す文字列内でセミコロンを使用しないでください。使用するEXECUTE IMMEDIATE
と、ORA-00911 '無効な文字' エラーが発生します。
SQL> BEGIN
2 EXECUTE IMMEDIATE 'DROP TABLE SP_AD_B;';
3 END;
4 /
BEGIN
*
ERROR at line 1:
ORA-00911: invalid character
ORA-06512: at line 2
これを実行した後、テーブルがまだ存在することを確認できます。
SQL> SELECT * FROM SP_AD_B;
no rows selected
(私はあなたのテーブルを持っていないので、単一の整数列を含むSP_AD_B
名前のテーブルを作成しました。データを入れる必要はありませんでした。)SP_AD_B
外側のセミコロンではなく、文字列の内側のセミコロンを削除すると、次のように機能します。
SQL> BEGIN
2 EXECUTE IMMEDIATE 'DROP TABLE SP_AD_B';
3 END;
4 /
PL/SQL procedure successfully completed.
SQL> SELECT * FROM SP_AD_B;
SELECT * FROM SP_AD_B
*
ERROR at line 1:
ORA-00942: table or view does not exist
テーブルがなくなったので、クエリを実行しようとするとエラーが発生します。
うまくいけば、これにより、スクリプトが機能して関連するテーブルが削除されるようにスクリプトを修正できるはずです。
しかし、出力メッセージで役立つ情報が得られなかったのはなぜでしょうか? さて、SP_AD_B
テーブルを再作成し、セミコロンを再導入して、テーブルをもう一度ドロップしてみますが、EXCEPTION
あなたと同様のハンドラーを使用します。
SQL> BEGIN
2 EXECUTE IMMEDIATE 'DROP TABLE SP_AD_B;';
3 EXCEPTION
4 WHEN OTHERS THEN
5 dbms_output.put_line('Exception, rolling back transaction, SP_AD not resolved.');
6 END;
7 /
Exception, rolling back transaction, SP_AD not resolved.
PL/SQL procedure successfully completed.
この場合、問題が発生したことを示すエラー メッセージが表示されたため、テーブルは削除されませんでした。しかし、何がうまくいかなかったのですか?Oracle がレポートできるエラーは数千あり、エラー メッセージを知らずに問題を推測するのは困難な場合があります。
ここで取るべきアプローチはいくつかあります。まず、エラー メッセージを に書き込むことができSQLERRM
ますdbms_output
。
SQL> BEGIN
2 EXECUTE IMMEDIATE 'DROP TABLE SP_AD_B;';
3 EXCEPTION
4 WHEN OTHERS THEN
5 dbms_output.put_line('Exception, rolling back transaction, SP_AD not resolved.');
6 dbms_output.put_line('Error message was: ' || SQLERRM);
7 END;
8 /
Exception, rolling back transaction, SP_AD not resolved.
Error message was: ORA-00911: invalid character
PL/SQL procedure successfully completed.
dbms_utility.format_error_backtrace
必要に応じて、現在のスタックトレースを文字列として返すために使用することもできます。これにより、エラーの原因を突き止めることができます。
または、例外を再発生させることもできます。ハンドラーRAISE
で単独で使用すると、現在の例外が再発生します。EXCEPTION
SQL> BEGIN
2 EXECUTE IMMEDIATE 'DROP TABLE SP_AD_B;';
3 EXCEPTION
4 WHEN OTHERS THEN
5 dbms_output.put_line('Exception, rolling back transaction, SP_AD not resolved.');
6 RAISE;
7 END;
8 /
Exception, rolling back transaction, SP_AD not resolved.
BEGIN
*
ERROR at line 1:
ORA-00911: invalid character
ORA-06512: at line 6
ただし、EXCEPTION
ハンドラーが実際には何の役にも立たないという事実を考えると、最善の方法はおそらくハンドラーを完全に取り除くことです。
CREATE
、、またはなどALTER
のDDL ステートメントをコミットまたはロールバックできないため、例外ハンドラーは何も達成しません。これらの各ステートメントは、実行の直前と直後に を発行します。aが成功しても aが失敗した場合、トランザクションをロールバックしてもドロップされたテーブルを元に戻すことはできません。andステートメントを削除することをお勧めします。DROP
TRUNCATE
COMMIT
DROP
RENAME
COMMIT WORK
ROLLBACK WORK
最後に、コメンターの Jeffrey Kemp が次の行に気付きました。
SELECT SOURCE INTO source FROM map_switch WHERE ROWNUM = 1;
これは、テーブルの任意の行からsource
の列の値という名前の変数に割り当てます。それは任意の行である可能性があります。順序を指定していないため、Oracle は自由に行を並べ替えることができます。SOURCE
map_switch
map_switch
テーブルに行が 1 つしかない場合は、どの行が返されるかは明らかです。しかし、これが事実である場合、なぜ指定するのROWNUM = 1
ですか?テーブルには複数の行がありROWNUM = 1
、「正確なフェッチが要求された行数を超えて返される」というエラーを黙らせるだけですか?
次のようなことをしたほうがよいでしょう。
SELECT SOURCE INTO source
FROM (SELECT SOURCE FROM map_switch ORDER BY some_column)
WHERE ROWNUM = 1;
map_switch
あなたのテーブルにどの列があるのか わかりません some_column
。そのため、上記の列をプレースホルダーとして使用しました。可能であれば、一意の値を持つ列を選択してください。
SELECT ... WHERE ROWNUM = 1 ORDER BY some_column
ソートを行う前に句を適用するような単純な方法はできないことに注意してくださいROWNUM = 1
。単一の行をソートしても、返される順序は 1 つしかないため、あまり意味がありません。