カーソルの操作¶
カーソルを使用して、一度に1行ずつクエリ結果を反復処理できます。
概要¶
クエリの結果からデータを取得するには、カーソルを使用できます。結果の行を反復処理するには、 ループ でカーソルを使用できます。
カーソルを使用するには、次を実行します。
カーソルを初めて使用する前に、 OPEN コマンドを実行し、 カーソルを開きます。これにより、クエリが実行され、結果がカーソルにロードされます。
FETCH コマンドを実行して、 1つ以上の行をフェッチ し、それらの行を処理します。
注釈
Snowflake Scriptingを使用する場合、 RESULTSET を使用してクエリの結果を取得することもできます。カーソルと RESULTSET の違いについては、 カーソルと RESULTSET の違いを理解する をご参照ください。
例に対するデータの設定¶
このセクションの例では、次のデータを使用しています。
カーソルの宣言¶
SELECT ステートメントまたは RESULTSET のカーソルを宣言できます。
ブロックの DECLARE セクションまたはブロックの BEGIN ... END セクションでカーソルを宣言します。
DECLARE セクション内において、 カーソル宣言構文 で説明されている構文を使用します。
たとえば、クエリのカーソルを宣言するには、次を実行します。
RESULTSET のカーソルを宣言するには、
BEGIN ... END ブロック内において、 カーソル割り当て構文 で説明されている構文を使用します。例:
SELECT ステートメントでは、カーソルを開いたときに変数にバインドできるバインドパラメーター(? 文字)を指定できます。変数をパラメーターにバインドするには、 OPEN コマンドの USING 句で変数を指定します。例:
Note: If you use Snowflake CLI, SnowSQL, the Classic Console, or the
execute_stream or execute_string method in Python Connector
code, use this example instead (see Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):
カーソルを開く¶
カーソルを宣言するステートメントは、そのカーソルに関連付けられたクエリを定義しますが、 OPEN コマンドを実行してカーソルを開くまで、クエリは実行されません。例:
注釈
FOR ループでカーソルを使用する場合は、カーソルを明示的に開く必要はありません。
RESULTSET オブジェクトのカーソルを宣言すると、オブジェクトをクエリに関連付けるときにクエリが実行されます。この場合は、カーソルを開いてもクエリは再度実行されません。
クエリにバインドパラメーター(? 文字)が含まれている場合は、 USING 句を追加して、それらのパラメータにバインドする変数のリストを指定します。例:
カーソルを開くと、クエリが実行され、指定された行がカーソルに取得され、最初の行をポイントする内部ポインターが設定されます。 カーソルを使用して個々の行をフェッチ(読み取り)する ために、 FETCH コマンドを使用できます。
他の SQL クエリと同様に、クエリ定義に最外部レベルの ORDER BY が含まれていない場合、結果セットには定義された順序がありません。カーソルの結果セットが作成されると、カーソルが閉じられるまで行の順序が保持されます。カーソルを再度宣言するか開くと、行の順序が異なる場合があります。同様に、カーソルを閉じて、カーソルを再度開く前に基になるテーブルが更新されると、結果セットが変更される可能性があります。
カーソルを使用したデータのフェッチ¶
FETCH コマンドを使用して、結果セットから現在の行を取得し、内部の現在の行ポインターを進めて、結果セットの次の行をポイントします。
INTO 句では、行の値を保持する変数を指定します。
例:
変数の数がカーソル宣言の SELECT 句の式の数と一致しない場合、Snowflakeは変数を位置によって列と一致させようとします。
列よりも多くの変数がある場合、Snowflakeは残りの変数を未設定のままにします。
変数よりも多くの列がある場合、Snowflakeは残りの列を無視します。
後続の各 FETCH コマンドは、最後の行がフェッチされるまで次の行を取得します。最後の行よりも後の行を FETCH しようとすると、 NULL 値を取得します。
RESULTSET またはカーソルは、クエリの実行時に結果セットのすべての行をキャッシュする必要はありません。FETCH 操作で遅延が発生する可能性があります。
カーソルの使用による GEOGRAPHY 値の取得¶
結果に型 GEOGRAPHY の列が含まれている場合、列の値の型は GEOGRAPHY ではなく OBJECT です。これは、 GEOGRAPHY オブジェクトを入力として受け入れる 地理空間関数 にこの値を直接渡すことができないことを意味します。
これを回避するには、列の値を GEOGRAPHY 型にキャストします。
カーソルのテーブルを返す¶
カーソルからデータのテーブルを返す必要がある場合は、カーソルを RESULTSET_FROM_CURSOR(cursor) に渡すことができます。その次に、カーソルを TABLE(...) に渡すことができます。
次のブロックは、カーソルからデータのテーブルを返します。
Note: If you use Snowflake CLI, SnowSQL, the Classic Console, or the
execute_stream or execute_string method in Python Connector
code, use this example instead (see Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):
すでにカーソルを使用して 行をフェッチ した場合でも、 RESULTSET_FROM_CURSOR は、内部行ポインタから始まる行だけでなく、すべての行を含む RESULTSET を返します。
上に示したように、この例では最初の行をフェッチし、内部行ポインターを2番目の行に設定します。 RESULTSET_FROM_CURSOR は、(2番目の行だけでなく)両方の行を含む RESULTSET を返します。
カーソルを閉じる¶
結果セットが完了したら、 CLOSE コマンドを実行してカーソルを閉じます。例:
注釈
FOR ループでカーソルを使用する場合は、カーソルを明示的に閉じる必要はありません。
閉じたカーソルに対しては、 FETCH コマンドを実行することはできません。
また、カーソルを閉じると、現在の行ポインターが無効になります。カーソルをもう一度開くと、ポインターは新しい結果セットの最初の行をポイントします。
カーソルの使用例¶
この例では、 例に対するデータの設定 で設定したデータを使用しています。
以下は、カーソルを使用して2つの行を読み取り、それらの行の価格を合計する匿名ブロックです。
Note: If you use Snowflake CLI, SnowSQL, the Classic Console, or the
execute_stream or execute_string method in Python Connector
code, use this example instead (see Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):
FOR ループ でカーソルを使っても同じ結果が得られます。
Note: If you use Snowflake CLI, SnowSQL, the Classic Console, or the
execute_stream or execute_string method in Python Connector
code, use this example instead (see Using Snowflake Scripting in Snowflake CLI, SnowSQL, and Python Connector):
カーソルに関する問題のトラブルシューティング¶
次のセクションでは、カーソルに関する一般的な問題について説明し、それぞれのケースで考えられる原因と解決策を示します。
症状: カーソルがすべての行ではなく、2行ごとに取得する¶
考えられる原因: FOR
<記録>IN<カーソル>ループ内で FETCH を実行した可能性があります。カーソル上の FOR ループは、自動的に次行をフェッチします。ループ内で別のフェッチを実行すると、2行ごとに取得されます。考えられる解決策: FOR ループ内の不要な FETCH コマンドを削除してください。
症状: FETCH コマンドが予期しない NULL 値を取得する¶
考えられる原因: FOR
<記録>IN<カーソル>ループ内で FETCH を実行した可能性があります。カーソル上の FOR ループは、自動的に次行をフェッチします。ループ内で別のフェッチを実行すると、2行ごとに取得されます。行数が奇数の場合、最後のフェッチは最後の行を超える行をフェッチしようとし、値は NULL になります。考えられる解決策: FOR ループ内の不要な FETCH コマンドを削除してください。