SQLShack (日本語)
SQLServerカーソルはインターネットで一般的なトピックの1つです。それらを使用する場合と使用しない場合では、さまざまな意見があります。今日は、それらについても話し、いつ使用するか(使用しないか)という質問に答えます。
データモデルと一般的な考え方
前回の記事、SQLの概要サーバーループについては、SQL Serverループについて説明しましたが、データベースのデータは使用していません。それは奇妙なことでしたが、今ではもっと明確になるはずです。今日は、カーソルについて説明しながら、データベースのデータを使用して、カーソルを使用する場合と使用しない場合を示します。使用するデータモデルは、このシリーズ全体で使用しているものと同じです。
SQLServerは3をサポートしますカーソルのさまざまな実装– Transact-SQLカーソル、APIカーソル、およびクライアントカーソル。この記事では、Transact-SQLカーソルに焦点を当てます。それらはDECLARECURSOR構文に基づいているため、簡単に認識できます。
SQL Serverカーソル–はじめに
コードと例に移る前に、SQLServerカーソルについて説明する必要があります。
SQL ServerカーソルはT-SQLロジックであり、関連するクエリ結果をループできます。これにより、アクションを順番に実行できます。たとえば、単一の行で更新を実行できます。
これが役立つ場合もありますが、データベースを操作する場合は、手続き型プログラミングパターンを使用しないでください。むしろ宣言型プログラミングに固執します。主な理由の1つは、DBMSがデータセットに対してアクションを実行するようにすでに最適化されているため、「システムよりも賢く」しようとしている人であってはならないということです。
それでも、それは良いことです。それらがどのように機能するかを知るために。他に何もなければ、継承するコードでそれらに会い、ロジックを書き直す必要があります。そして、何かをする前に、それがどのように機能するかを理解する必要があります。
したがって、カーソルが必要な場合は、次のことを知っておく必要があります。
- カーソルは変数を使用して、ループの各部分で返される値を格納します。したがって、宣言する必要があります。必要なすべての変数
- 次に行うことは、DECLARE…CURSOR FOR SELECTクエリです。ここで、カーソルを宣言し、そのカーソルに関連する(データを入力する)クエリを定義します。
- カーソルを開き、カーソルからNEXTをフェッチします
- WHILEループで、@@ FETCH_STATUS変数(WHILE @@ FETCH_STATUS = 0)をテストします。条件が成立する場合は、ループに入るBEGIN …ENDブロックを実行し、そのブロック内でステートメントを実行します。
- 結果セット全体をループした後、ループを終了します。カーソルを閉じて、割り当てを解除する必要があります。カーソルの定義が削除され、使用されているメモリが解放されるため、割り当て解除は重要です。
SQL Serverカーソル–例
次に、2つのカーソルの例を見てみましょう。これらは非常に単純ですが、カーソルがどのように機能するかをうまく説明しています。
最初の例では、すべての都市のIDと名前、および関連する国の名前を取得します。 PRINTコマンドを使用して、ループの各パスの組み合わせを出力します。
SQLServerカーソルとwhileループは、すべての都市のIDと名前、および関連する国のIDと名前をデータベースに正確に返しました。
ここで言及する最も重要なことは、この結果セットを簡単に返すことができるということです。カーソルのDECLARE部分に格納されている元のSQLクエリを使用するため、カーソルは必要ありませんでした。
次に進みます。もう1つの例を示します。今回は、情報スキーマデータベースにクエリを実行して、テーブル名順に並べられた最初の5つのテーブルを返します。このようなクエリを使用する意味はあまりありませんが、この例は次のことを示しています。
- 情報スキーマデータベースにクエリを実行する方法
- いくつかのコマンド/ステートメントを組み合わせる方法以前の記事で言及したことがあります(IF…ELSE、WHILEループ、CONCAT)
コーディング側から、今回は、ループ内に何も出力せず、CONCATを使用して文字列を作成したことを強調したいと思います。また、IFステートメントを使用して、最初のパスにあるかどうかをテストしました。最初のパスにある場合は、「、」を追加していません。そうでない場合は、文字列に「、」を追加します。
ループの後、結果文字列を出力し、カーソルを閉じて割り当てを解除しました。
これは、STRING_AGG関数を使用して実現できます。これはSQLServer 2017以降で利用可能であり、MySQLGROUP_CONCAT関数と同等です。
SQLServerカーソル–いつ使用するか(使用しないか)?
試してみます「SQLServerカーソルを使用する必要がある場合と使用しない場合」という質問に客観的に答えてください。時間の経過とともに状況が変化し、カーソル、カーソルを「置き換える」他のオブジェクトのいずれかを改善する必要があるため、考慮に入れてください。この記事が書かれた日付。それでは、始めましょう。
カーソルは使用しないでください:
- ほとんどの場合🙂これはばかげているように聞こえるかもしれませんが、ほとんどの場合に当てはまります。 SQL Serverは、カーソルを使用して解決しようとする可能性のあることを正確に実行する、多数のオブジェクト&関数を実装しています。カーソルを使用することを決定する前に、カーソルが唯一の可能な(適切な)解決策であると結論付けるのに十分な調査を行ったことを確認してください。同じことがデータベースのループを表します。前回の記事「SQLServerループの概要」では、ループを使用しましたが、データをループすることはしませんでした。
カーソルを使用できます:
- 主に、バックアップ、整合性チェック、インデックスの再構築などのデータベース管理タスクに使用します
- 1回限りパフォーマンスの低下がシステム全体のパフォーマンスに影響を与えないことが確実な場合のタスク
-
さまざまなパラメータを使用してストアドプロシージャを数回呼び出す。その場合、カーソル変数からパラメータを取得し、ループ内で呼び出しを行います
カーソル(またはループ)内でストアドプロシージャまたは別のクエリを呼び出すと、パフォーマンスに大きな影響があります。カーソルループでは、最初からクエリ/プロシージャを実行します。そうすることにした場合は、起こりうる結果に注意する必要があります。
- 前のヒントでは、カーソルを使用する必要がある場合の最後の箇条書きを示しています。それらがどのように機能するかを完全に理解していて、パフォーマンスに影響を与えないと確信している場合は、それを試してみてください。
SQL Serverカーソル–人々がそれらを使用する(使用しない)理由?
最後に答えたい質問は、なぜ誰かがカーソルを使用するのかということです。
- パフォーマンスに影響を与えない1回限りの仕事や通常の行動にそれらを使用している人には、言い訳があります。その理由の1つは、そのようなコードが手続き型コードであり、それに慣れている場合は非常に読みやすいことです。
- 一方、データベースについて学び始め、手続き型プログラミングに慣れている人は、前述のように、カーソルはデータベースよりも手続き型プログラミングに非常に近いため、カーソルを使用します。これはそれらを使用する理由ではありません。なぜなら、ここでの唯一の言い訳は、物事を成し遂げる他の(正しい)方法を単に知らないということです。
- カーソルについて最も重要なことは、それらがSQLステートメントと比較すると遅いため、遅かれ早かれパフォーマンスの問題が発生するため、使用を避ける必要があります(何をしているのか、その理由を正確に理解していない限り)
Iカーソルの概念を理解しておくと便利です。カーソルに出会う可能性が非常に高いからです。これらは、SQLServerにいくつかの新しいオプションが追加される前に人気がありました。また、使用する前に誰かがシステムで作業を続ける可能性があり、停止した場所から続行する必要があります。カーソル(手続き型コード)をSQL(宣言型コード)に置き換える必要があるかもしれません。
結論
カーソルについては、使用しないでください。 🙂SQLServerは、以前は宣言型コードを使用して解決するのが困難であった問題を解決する多くの変更を実装しました。何か新しいことを調査して学び、最後に最適なコードを作成するために時間を費やしたほうがよいでしょう。もちろん、その理由がわかっていて、それらに関連して発生する可能性のある問題を認識している場合は、それらを使用できます。
目次
SQLの学習:CREATE DATABASE & CREATETABLE操作
SQLの学習:INSERT INTO TABLE
SQLの学習:プライマリキー
SQLの学習:外部キー
SQLの学習:SELECTステートメント
SQLの学習:内部結合と左結合
SQLの学習:SQLスクリプト
SQLの学習:関係の種類
SQLの学習:複数のテーブルを結合する
SQLの学習:集計関数
SQLの学習:複雑なSELECTクエリの書き方
SQLの学習:INFORMATION_SCHEMAデータベース
SQLの学習:SQLデータタイプ
SQLの学習:理論の設定
SQLの学習:ユーザー定義関数
SQLの学習:ユーザー定義のストアドプロシージャ
SQLの学習:SQLビュー
SQLの学習:SQLトリガー
SQLの学習:SQLクエリの練習
SQLの学習:SQLクエリの例
SQLの学習:SQLクエリを使用して手動でレポートを作成する
SQLの学習:SQLServerの日付と時刻の関数
SQLの学習:SQLServerレポートの作成日付と時刻関数の使用
SQLの学習:SQLServerピボットテーブル
SQLの学習:SQLServerのExcelへのエクスポート
SQLの学習:SQLServerループの概要
SQLの学習:SQLServerのカーソル
SQLの学習:データの削除と更新に関するSQLのベストプラクティス
SQLの学習:命名規則
SQLの学習:SQL関連のジョブ
SQLの学習:SQLServerでの非等価結合
SQLの学習:SQLインジェクション
- 作成者
- 最近の投稿
彼の過去と現在の取り組みは、データベースの設計とコーディングから、データベースに関する教育、コンサルティング、執筆までさまざまです。また、BI、アルゴリズムの作成、チェス、フィラテリー、犬2匹、猫2匹、妻1匹、赤ちゃん1匹…
LinkedInで彼を見つけることができます
EmilDrkusicによる投稿をすべて表示
- SQLの学習:SQLインジェクション-2020年11月2日
- SQLの学習:SQLServerでの非等価結合-2020年9月29日
- SQLの学習: SQL関連のジョブ-2020年9月1日