logo

SQL Server のカーソル

SQL Server のカーソルは 一度に各行を取得し、そのデータを操作できるようにする atabase オブジェクト 。カーソルは行へのポインタにすぎません。常に SELECT ステートメントと組み合わせて使用​​されます。通常は以下のコレクションです SQL 所定の数の行を 1 つずつループするロジック。カーソルの簡単な例は、従業員の記録の広範なデータベースがあり、税金と休暇を差し引いた各従業員の給与を計算したい場合です。

SQL サーバー カーソルの目的は、データを行ごとに更新、変更、またはすべてのレコードを一度に取得する場合には不可能な計算を実行することです。 。 SQL Server データベースのバックアップなどの管理タスクを順番に実行する場合にも役立ちます。カーソルは主に、開発、DBA、ETL プロセスで使用されます。

この記事では、カーソルのライフサイクル、カーソルが使用される理由とタイミング、カーソルの実装方法、その制限事項、カーソルの置き換え方法など、SQL Server カーソルに関するすべてについて説明します。

カーソルのライフサイクル

カーソルのライフサイクルを次のように記述することができます。 5つの異なるセクション 次のように:

SQL Server のカーソル

1: カーソルの宣言

最初のステップは、以下の SQL ステートメントを使用してカーソルを宣言することです。

文字列が長すぎる
 DECLARE cursor_name CURSOR FOR select_statement; 

DECLARE キーワードの後に​​データ型 CURSOR を使用して名前を指定することで、カーソルを宣言できます。次に、カーソルの出力を定義する SELECT ステートメントを作成します。

2: カーソルを開く

これは 2 番目のステップで、カーソルを開いて結果セットから取得したデータを保存します。これは、以下の SQL ステートメントを使用して行うことができます。

 OPEN cursor_name; 

3: カーソルのフェッチ

これは 3 番目のステップで、行を 1 つずつ、またはブロック単位でフェッチして、カーソル内の現在アクティブな行に対して挿入、更新、削除操作などのデータ操作を行うことができます。これは、以下の SQL ステートメントを使用して行うことができます。

 FETCH NEXT FROM cursor INTO variable_list; 

を使用することもできます。 @@FETCHSTATUS関数 SQL Server で、カーソルに対して実行された最新の FETCH ステートメント カーソルのステータスを取得します。の フェッチ @@FETCHSTATUS の出力がゼロの場合、ステートメントは成功しました。の その間 ステートメントを使用すると、カーソルからすべてのレコードを取得できます。次のコードはそれをより明確に説明しています。

 WHILE @@FETCH_STATUS = 0 BEGIN FETCH NEXT FROM cursor_name; END; 

4: カーソルを閉じる

これは 4 番目のステップで、カーソルでの作業が終了したらカーソルを閉じる必要があります。これは、以下の SQL ステートメントを使用して行うことができます。

 CLOSE cursor_name; 

5: カーソルの割り当てを解除する

これは 5 番目で最後のステップで、カーソル定義を消去し、カーソルに関連付けられているすべてのシステム リソースを解放します。これは、以下の SQL ステートメントを使用して行うことができます。

 DEALLOCATE cursor_name; 

SQL Server カーソルの使用

SQL Server を含むリレーショナル データベース管理システムは、結果セットと呼ばれる一連の行のデータの処理に優れていることがわかっています。 例えば 、テーブルがあります 製品テーブル 製品の説明が含まれています。を更新したい場合は、 価格 製品の、その後、以下の ' アップデート' クエリは、「」の条件に一致するすべてのレコードを更新します。 どこ' 句:

 UPDATE product_table SET unit_price = 100 WHERE product_id = 105; 

場合によっては、アプリケーションは行をシングルトン方式で処理する必要があります。つまり、結果セット全体を一度に処理するのではなく、行ごとに処理する必要があります。このプロセスは、SQL Server のカーソルを使用して実行できます。カーソルを使用する前に、カーソルはパフォーマンスが非常に悪いため、常にカーソル以外にオプションがない場合にのみ使用する必要があることを理解しておく必要があります。

カーソルは、すべてのプログラミング言語で一度に 1 つのオブジェクトを反復するために FOREACH、FOR、WHILE、DO WHILE などのループを使用するのと同じ手法を使用します。したがって、プログラミング言語のループ プロセスと同じロジックを適用するため、これが選択される可能性があります。

SQL Server のカーソルの種類

SQL Server のさまざまな種類のカーソルを以下に示します。

  • 静的カーソル
  • 動的カーソル
  • 前方専用カーソル
  • キーセット カーソル
SQL Server のカーソル

静的カーソル

静的カーソルによって表示される結果セットは、カーソルが最初に開かれたときと常に同じです。静的カーソルは結果を次のように保存するため、 tempdb 、彼らはいつも 読み取り専用 。静的カーソルを使用して、前後に移動できます。他のカーソルとは対照的に、速度が遅く、より多くのメモリを消費します。その結果、スクロールが必要な場合にのみ使用でき、他のカーソルは適していません。

このカーソルには、データベースを開いた後にデータベースから削除された行が表示されます。静的カーソルは、INSERT、UPDATE、または DELETE 操作を表しません (カーソルが閉じて再度開かれない限り)。

動的カーソル

動的カーソルは、カーソルが開いている間にデータの更新、削除、挿入操作を実行できる静的カーソルとは反対です。それは デフォルトでスクロール可能 。変更がカーソル内で発生したかカーソル外で発生したかに関係なく、結果セット内の行、順序、値に加えられたすべての変更を検出できます。カーソルの外側では、コミットされるまで更新を確認できません。

前方専用カーソル

これは、すべてのカーソルの中でデフォルトで最速のカーソル タイプです。これは、前方専用カーソルと呼ばれます。 結果セットを前方にのみ移動します 。このカーソルはスクロールをサポートしていません。結果セットの先頭から末尾までの行のみを取得できます。これにより、挿入、更新、削除の操作を実行できるようになります。ここでは、結果セット内の行に影響を与える、ユーザーが行った挿入、更新、および削除操作の影響が、行がカーソルからフェッチされるときに表示されます。行がフェッチされたときに、カーソルを介して行に加えられた変更を確認することはできません。

前方専用カーソルは、次の 3 つのタイプに分類されます。

インターフェースとは何ですか
  1. Forward_Only キーセット
  2. 静的転送のみ
  3. 早送り
SQL Server のカーソル

キーセット駆動のカーソル

このカーソル機能は 静的カーソルと動的カーソルの間にあります 変化を検出する能力について。静的カーソルのように、結果セットのメンバーシップや順序の変更を常に検出できるわけではありません。動的カーソルと同様に、結果セットの行値の変更を検出できます。それができるのは、 最初の行から最後へ、最後から最初の行へ移動します 。このカーソルが開かれるたびに、順序とメンバーシップが固定されます。

これは、キーセット内のキーと同じ一意の識別子のセットによって操作されます。キーセットは、カーソルが最初に開かれたときに SELECT ステートメントを修飾したすべての行によって決定されます。また、更新および削除操作をサポートするデータ ソースへの変更を検出することもできます。デフォルトではスクロール可能です。

例の実装

SQL サーバーにカーソルの例を実装してみましょう。これを行うには、まず「」という名前のテーブルを作成します。 お客様 ' 以下のステートメントを使用します。

 CREATE TABLE customer ( id int PRIMARY KEY, c_name nvarchar(45) NOT NULL, email nvarchar(45) NOT NULL, city nvarchar(25) NOT NULL ); 

次に、テーブルに値を挿入します。以下のステートメントを実行して、テーブルにデータを追加できます。

 INSERT INTO customer (id, c_name, email, city) VALUES (1,'Steffen', '[email protected]', 'Texas'), (2, 'Joseph', '[email protected]', 'Alaska'), (3, 'Peter', '[email protected]', 'California'), (4,'Donald', '[email protected]', 'New York'), (5, 'Kevin', '[email protected]', 'Florida'), (6, 'Marielia', '[email protected]', 'Arizona'), (7,'Antonio', '[email protected]', 'New York'), (8, 'Diego', '[email protected]', 'California'); 

以下を実行することでデータを確認できます。 選択する 声明:

 SELECT * FROM customer; 

クエリを実行すると、以下の出力が表示されます。 8行 テーブルに:

SQL Server のカーソル

次に、顧客レコードを表示するカーソルを作成します。以下のコード スニペットは、カーソルの宣言または作成のすべての手順をまとめて説明しています。

Java言語の面接での質問
 --Declare the variables for holding data. DECLARE @id INT, @c_name NVARCHAR(50), @city NVARCHAR(50) --Declare and set counter. DECLARE @Counter INT SET @Counter = 1 --Declare a cursor DECLARE PrintCustomers CURSOR FOR SELECT id, c_name, city FROM customer --Open cursor OPEN PrintCustomers --Fetch the record into the variables. FETCH NEXT FROM PrintCustomers INTO @id, @c_name, @city --LOOP UNTIL RECORDS ARE AVAILABLE. WHILE @@FETCH_STATUS = 0 BEGIN IF @Counter = 1 BEGIN PRINT 'id' + CHAR(9) + 'c_name' + CHAR(9) + CHAR(9) + 'city' PRINT '--------------------------' END --Print the current record PRINT CAST(@id AS NVARCHAR(10)) + CHAR(9) + @c_name + CHAR(9) + CHAR(9) + @city --Increment the counter variable SET @Counter = @Counter + 1 --Fetch the next record into the variables. FETCH NEXT FROM PrintCustomers INTO @id, @c_name, @city END --Close the cursor CLOSE PrintCustomers --Deallocate the cursor DEALLOCATE PrintCustomers 

カーソルを実行すると、以下の出力が得られます。

SQL Server のカーソル

SQL Server カーソルの制限事項

カーソルにはいくつかの制限があるため、常にカーソル以外にオプションがない場合にのみ使用する必要があります。これらの制限は次のとおりです。

  • カーソルは、レコードを取得するたびにネットワーク ラウンドトリップを必要とするため、ネットワーク リソースを消費します。
  • カーソルはメモリに常駐する一連のポインタです。つまり、カーソルはマシン上で他のプロセスが使用できるメモリを必要とします。
  • データを処理するときに、テーブルの一部またはテーブル全体にロックを課します。
  • カーソルはテーブル レコードを一度に 1 行ずつ更新するため、パフォーマンスと速度が遅くなります。
  • カーソルは while ループよりも高速ですが、オーバーヘッドが大きくなります。
  • カーソルに取り込まれる行と列の数は、カーソルの速度に影響を与えるもう 1 つの側面です。これは、カーソルを開いてフェッチ ステートメントを実行するのにかかる時間を指します。

どうすればカーソルを回避できるでしょうか?

カーソルの主な仕事は、テーブルを行ごとに移動することです。カーソルを回避する最も簡単な方法を以下に示します。

SQL while ループの使用

カーソルの使用を回避する最も簡単な方法は、一時テーブルに結果セットを挿入できる while ループを使用することです。

ユーザー定義関数

場合によっては、結果の行セットを計算するためにカーソルが使用されます。これは、要件を満たすユーザー定義関数を使用することで実現できます。

結合の使用

結合では、指定された条件を満たす列のみが処理されるため、コード行が減り、巨大なレコードを処理する必要がある場合にカーソルよりも高速なパフォーマンスが得られます。