SQL Server のカーソル (CURSOR) のスコープ
SQL Server のカーソル (CURSOR) 名のスコープは?
パフォーマンスを考えるとできるだけ使わないほうが良いとわかっていても、カーソル (CURSOR) を使わなければならないケースは出てくるものです。
そんなカーソル (CURSOR) ですが、ちょっと気をつけなければいけないのがカーソル名のスコープです。
カーソル (CURSOR) のデフォルトのスコープは接続に対してグローバル
この記事を書いている時点の最新の SQL Server は SQL Server 2008 R2 ですが、カーソル名のデフォルトスコープは、デフォルトで接続に対してグローバル (GLOBAL) になっています。
マイクロソフトによると、これは SQL Server Version 7.0 以前のバージョンとの互換性をとるためだそうです。
ですので、同じ名前のカーソルを複数のストアードプロシジャーで使い、それが同じ接続でほぼ同時に実行されると、先に実行されたストアードプロシジャーでカーソルが作成されて開かれたままで、後に実行されたほうのストアードプロシジャーがカーソルを作成しようとした時に、カーソルがもう存在しますよという以下のようなエラーが出てしまいます。
A cursor with the name 'CursorName' already exists.
あまり起こることではないかもしれませんが、カーソルを使う時には名前がかぶらないようにするか、データベースのカーソル名のデフォルトスコープをローカル (LOCAL) にしておくと良いでしょう。
カーソル (CURSOR) のデフォルトスコープの確認の方法
まず現在のデータベースのカーソル (CURSOR) のデフォルトスコープの設定を確認してみましょう。
sys.databases の is_local_cursor_default カラムの値が 0 のときは、カーソルのスコープがグローバル(デフォルト)、1 の時はローカルになっています。
以下のクエリーを実行して、Test という名前のデータベースの is_local_cursor_default の値をチェックします。
FROM sys.databases
WHERE name = 'Test';
is_local_cursor_default カラムの値が 0 なので、現在の Test データベースのカーソル名のデフォルトスコープはグローバルです。
カーソル (CURSOR) のデフォルトスコープの変更の方法
カーソル (CURSOR) のデフォルトスコープを変更するには ALTER DATABASE を使います。
ALTER DATABASE [DatabaseName] SET CURSOR_DEFAULT LOCAL;
を実行するとデータベースのカーソル (CURSOR) のデフォルトスコープを LOCAL に、
ALTER DATABASE [DatabaseName] SET CURSOR_DEFAULT GLOBAL;
を実行するとデータベースのカーソルのデフォルトスコープを GLOBAL に変更することができます。
以下のクエリーを実行して Test データベースのデフォルトカーソルスコープをローカルにします。
SET CURSOR_DEFAULT LOCAL;
先ほどのクエリーで確認すると is_local_cursor_default カラムの値が 1 (Local) になっていますね。
カーソル (CURSOR) のスコープを指定する方法
DECLARE でカーソルを定義する際に、カーソルのスコープを指定することも可能です。
カーソルのスコープをローカル (LOCAL) にしたい時は、CURSOR の後に LOCAL オプションを次のように指定します。
LOCAL
FOR
SELECT ....
スコープのオプションは GLOBAL か LOCAL の指定が可能で、指定しない時は、先ほどのデータベースのカーソル (CURSOR) のデフォルトスコープが使われます。