Oracle SQLでセミコロンとスラッシュを使用する必要があるのはいつですか?


179

今週、私の会社では、SQLスクリプトをどのように記述するかについていくつかの議論がありました。

背景:データベースはOracle 10gです(間もなく11にアップグレードされます)。私たちのDBAチームは、SQLPlusを使用して、スクリプトを運用環境に展開します。

現在、セミコロンとスラッシュ(/)の両方を使用していたため、最近失敗したデプロイがありました。セミコロンは各ステートメントの最後にあり、スラッシュはステートメントの間にありました。

alter table foo.bar drop constraint bar1;
/
alter table foo.can drop constraint can1;
/

スクリプトの後半に追加されたトリガー、作成されたビュー、およびストアドプロシージャがありました。;との両方を持っている/、それぞれの文は、(特にユニークであるために必要な挿入、上の)エラーを引き起こして二回実行するようになりました。

SQL Developerではこれは起こりません、TOADではこれは起こりません。特定のコマンドを実行した場合、これらのコマンドがないと機能しません。/、それらの。

PL / SQLでは、サブプログラム(DECLARE、BEGIN、END)がある場合、使用されるセミコロンはサブプログラムの一部と見なされるため、スラッシュを使用する必要があります。

だから私の質問はこれです:データベースがOracleの場合、SQLスクリプトを記述する適切な方法は何ですか?DBがOracleであることを知っているので、常に/


1
誰かがSQLDeveloperでデータベースをエクスポートしている場合、「ターミネーター」と呼ばれるチェックボックスがあり、選択するとセミコロンを使用して各ステートメントを終了します。このオプションはデフォルトで選択されています。セミコロンを削除してステートメントの重複を避けるために選択を解除します
Ruslans Uralovs

7
この古いスレッドを無意味に殺して死に至らせるために、SQL言語にはセミコロンがないことを述べておきます。これは、SQL * Plusのデフォルトのターミネータ文字であり(必要sqlterminator!応じて設定できます)、この規則には他のツールが従う傾向があります。ただし、PL / SQL言語では、必須の構文要素としてセミコロンを使用します。
ウィリアム・ロバートソン、

回答:


31

それは好みの問題ですが、スラッシュを一貫して使用するスクリプトを見るのが好きです。このようにして、すべての「ユニット」の作業(PL / SQLオブジェクトの作成、PL / SQL匿名ブロックの実行、DMLステートメントの実行)を実行できます。目で簡単に取り出せます。

また、最終的にAntなどのデプロイメントに移行すると、ターゲットの定義が簡素化され、一貫したステートメント区切り文字が得られます。


1
この答えは、理由を説明していない/か、;それ以上のコンテキストのために@a_horse_with_no_nameまたは@Mr_Moneybagsの答えを参照してください
ケイ

333

私はこれが古いスレッドであることを知っていますが、私はそれに偶然出会っただけで、これは完全には説明されていないと感じています。

SQL * Plusでは、動作が異なるため、a /とaの意味には大きな違いがあります;

;両端のに対し、SQLステートメント、/現在の「バッファ」にあるものは何でも実行します。したがって、a ; a を使用する/、ステートメントは実際には2回実行されます。

/ステートメントを実行した後にを使用すると、簡単にそれを確認できます。

SQL*Plus: Release 11.2.0.1.0 Production on Wed Apr 18 12:37:20 2012

Copyright (c) 1982, 2010, Oracle.  All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning and OLAP options

SQL> drop table foo;

Table dropped.

SQL> /
drop table foo
           *
ERROR at line 1:
ORA-00942: table or view does not exist

この場合、実際にエラーに気づきます。


しかし、次のようなSQLスクリプトがあると仮定します。

drop table foo;
/

これはSQL * Plus内から実行されるため、非常に混乱します。

SQL*Plus: Release 11.2.0.1.0 Production on Wed Apr 18 12:38:05 2012

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning and OLAP options

SQL> @drop

Table dropped.

drop table foo
           *
ERROR at line 1:
ORA-00942: table or view does not exist

/主に埋め込まれているステートメントを実行するために必要とされる;ようにCREATE PROCEDURE声明を。


2
@amis、私はOracleが初めてで、同じ問題に遭遇します。この質問は非常に役に立ちますが、すべての回答で、「最善の方法」ではなく「なぜ」、またはこれを回避するための何らかの方法について説明しました。だから、私が正しく理解していれば、スクリプトを1つだけにして、それをすべてのツールで使用できるようにする方法はありません...または、何か方法を見つけますか?
ceinmart 2013年

5
@ceinmart:「最善の方法」は、SQLスクリプトを実行するための1つ(そして1つだけ)のツールを定義することです。そして、スクリプトの「正確さ」は、そのツールを使用して検証されます。プログラミング言語用の1つのコンパイラーまたはランタイム環境の特定のバージョン(Java 7、.Net 4.0、PHP 5.xなど)を持つのと同様
a_horse_with_no_name

1
いい答えだ。それは私だけですか、それとも他のDBと比較してOracleは間抜けで古風なものですか?私は多くのSybaseを使用してきましたが、はるかに直感的です。
スプラッシュアウト'10

1
@splashout:まあ、デフォルトの区切り文字(;)を含むステートメントを実行したい場合は、代替の区切り文字を指定する方法を見つける必要があります
a_horse_with_no_name

97

との間の使用法をさらに明確にしたかっ;/

SQLPLUSの場合:

  1. ; 「現在のステートメントを終了して実行し、SQLPLUSバッファに保存する」ことを意味します
  2. <newline>DML(SELECT、UPDATE、INSERT、...)ステートメントまたは一部のタイプのDDL(テーブルとビューの作成)ステートメント(を含まない;)の後、ステートメントをバッファーに格納しますが、実行しません。
  3. /ステートメントを(ブランクで<newline>)バッファーに入力した後は、「バッファーでDML、DDL、またはPL / SQLを実行します。
  4. RUN または R、バッファ内のSQLを表示/出力して実行するsqlsplusコマンドです。SQLステートメントは終了しません。
  5. / DML、DDL、またはPL / SQLの入力中は、「現在のステートメントを終了し、実行してSQLPLUSバッファに保存する」ことを意味します

注:ので;文を終了するためにPL / SQLを使用している;私たちは完全になるように全体PL / SQLブロックをしたいので「現在のステートメントを終了し、それを実行し、SQLPLUSバッファに格納し」を意味するSQLPLUSで使用することはできませんバッファし、それを実行します。PL / SQLブロックの末尾は次のとおりです。

END;
/

22

ほとんどすべてのOracleデプロイメントはSQL * Plus(DBAが使用する奇妙な小さなコマンドラインツール)を介して行われます。SQL * Plusでは、単一のスラッシュは基本的に「最後に実行したSQLまたはPL / SQLコマンドを再実行する」ことを意味します。

見る

http://ss64.com/ora/syntax-sqlplus.html

経験則では、スラッシュを使用BEGIN .. ENDできる場所または使用できる場所で使用しますCREATE OR REPLACE

ユニークな使用が必要なインサート用

INSERT INTO my_table ()
SELECT <values to be inserted>
FROM dual
WHERE NOT EXISTS (SELECT 
                  FROM my_table
                  WHERE <identify data that you are trying to insert>)

14

私の理解では、DDL、DML、DCL、およびTCLステートメントを含むすべてのSQLステートメントはセミコロンの最後で自動的に実行されるため、スラッシュは必要ありません。

プロシージャ、ファンクション、パッケージおよびトリガーを含む他のPL / SQLブロックの場合、それらは複数行プログラムであるため、Oracleはブロックをいつ実行するかを知る必要があるため、各ブロックの最後にスラッシュを記述して、 Oracleに実行させます。


1

各スクリプトの最後に1回だけスラッシュを使用して、sqlplusにコード行がもうないことを伝えます。スクリプトの途中で、スラッシュは使用しません。


最後に/が必要なもの(サブプログラムやトリガーなど)を注文しますか?複数のトリガーがある場合はどうなりますか?私はテストを実行し、各テストの間に/がない限り、最初のテストのみを実行します。何か不足していますか?
amischiefr 2009

私はそれを(可能な場合)を回避しようとするが、私は(トリガーのように)、私は正確にセミコロンとslashsを使用できない場合は、Oracleのサンプル・スキーマを生成する公式のスクリプトで使用されるように:download.oracle.com/docsを/cd/B19306_01/server.102/b14198/… 挿入の問題については、オブジェクトを作成するスクリプトを、テーブルにデータを入力するスクリプトから分離しようとしています。
ジョナサン

1
申し訳ありませんが、これは質問の答えにはなりません。
DerMike
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.