フロー演算子

フロー演算子は、 SQL ステートメントを連結し、あるステートメントの結果を別のステートメントの入力として使用します。現在、Snowflakeでサポートされているフロー演算子はパイプ演算子(->>)のみです。

パイプ

パイプ演算子は、コマンドライン上のUnixのパイプ(|)に似ていますが、Unixコマンドではなく SQL ステートメント用です。パイプ演算子を使用するには、演算子で区切られた一連の SQL ステートメントを指定します。SHOW、 SELECT、 CREATE、 INSERT など、有効な SQL ステートメントを指定できます。最初のステートメント(SQL)以降では、前のステートメントの結果を入力として受け取ることができます。FROM 句では、前の SQL ステートメントをドル記号($)とパイプ番号(現在のステートメントからさかのぼってチェーン内のステートメントの相対位置)のパラメーターで参照します。

パイプ演算子は、次の一連の SQL ステートメントを連結します。コメントには、各ステートメントの相対参照番号が示されています。

first_st -- Referenced as $4 in last_st, $3 in fourth_st, $2 in third_st, and $1 in second_st
  ->> second_st -- Referenced as $3 in last_st, $2 in fourth_st, and $1 in third_st
  ->> third_st  -- Referenced as $2 in last_st and $1 in fourth_st
  ->> fourth_st -- Referenced as $1 in last_st
  ->> last_st;
Copy

例えば、この一連の SQL ステートメントでは、3つの SELECT ステートメントにパイプ番号参照があり、それぞれが最初の SELECT ステートメントの結果を入力として受け取ります。

SELECT ...
  ->> SELECT ... FROM $1
  ->> SELECT ... FROM $2
  ->> SELECT ... FROM $3;
Copy

図のように、最後のステートメントの後にセミコロンを置くことで、 SQL ステートメントのチェーンを終わらせます。チェーンの前のステートメントの後にセミコロンを置かないでください。チェーン全体の出力は、最後の SQL ステートメントの最終結果です。SnowSQL などのクライアントツールは、ステートメントのチェーンを1つのステートメントとして扱います。

パイプ演算子には次のようなメリットがあります。

  • 依存関係 SQL ステートメントの実行を簡素化します。

  • 複雑な SQL 演算の読みやすさと柔軟性を向上させます。

構文

<sql_statement_1> ->> <sql_statement_2> [ ->> <sql_statement_n> ... ]
Copy

使用上の注意

  • 各ステートメントは、チェーンの後続ステートメントによってのみ消費できる結果を生成します。

  • ステートメントは指定された順序で実行されます。 RESULT_SCAN(LAST_QUERY_ID()) とは異なり、パイプ番号は、チェーン外で他のクエリが同時に実行されたかどうかに関わらず、チェーン内の正しい結果セットに解決されます。

  • ステートメントが前のステートメントの結果を消費する場合、消費される結果セットは、前のステートメントのクエリ ID を渡された RESULT_SCAN 関数によって返される結果セットと同じです。

    例えば、これらのステートメントは、 SHOW WAREHOUSES コマンドの出力を特定の列に制限します:

    SHOW WAREHOUSES;
    
    SELECT "name", "state", "type", "size"
      FROM TABLE(RESULT_SCAN(LAST_QUERY_ID(-1)));
    
    Copy

    このステートメントでは、パイプ演算子を使って同じ結果を生成します。

    SHOW WAREHOUSES
      ->> SELECT "name", "state", "type", "size" FROM $1;
    
    Copy
  • パイプ演算子を使用したクエリでは、チェーン内の前のクエリの入力結果セットと同じ順序で行を返すことは保証されません。クエリに ORDER BY 句を含めることで、順序を指定することができます。

  • SQL ステートメントによってエラーが発生すると、チェーンの実行は停止され、そのエラーがクライアントに返されます。

  • 最後のステートメントの結果がクライアントに返されます。

  • ステートメントは Snowflake Scripting 匿名ブロックとして実行されます。

制限事項

  • $n パラメーターは SQL ステートメントの FROM 句でのみ有効です。

  • 各 SQL ステートメントは、パイプチェーンの後続のステートメントによってのみ消費できる結果を生成します。結果は、最後のステートメントの結果を除いて、パイプチェーンの外部で消費することはできません。

  • 位置指定バインド変数はサポートされていません。

以下の例では、パイプ演算子を使用しています。

SHOW コマンドの出力用に列のリストを選択する

SHOW TABLES コマンドを実行し、パイプ演算子を使用して、2025年4月15日以降に作成されたテーブルの出力を created_onnameowner 列に制限します。

SHOW TABLES
  ->> SELECT "created_on" AS creation_date,
             "name" AS table_name,
             "owner" AS table_owner
        FROM $1
        WHERE creation_date > '2025-04-15'::DATE;
Copy
+-------------------------------+-------------+--------------+
| CREATION_DATE                 | TABLE_NAME  | TABLE_OWNER  |
|-------------------------------+-------------+--------------|
| 2025-04-16 08:46:16.130 -0700 | TEST_TABLE1 | ACCOUNTADMIN |
| 2025-04-16 09:44:13.701 -0700 | MYTABLE1    | USER_ROLE    |
| 2025-04-16 08:46:32.092 -0700 | MYTABLE2    | USER_ROLE    |
+-------------------------------+-------------+--------------+

複数のテーブルに対するクエリの結果を入力として受け取るクエリを実行する

まず、 dept_pipe_demo テーブルと emp_pipe_demo テーブルを作成し、それぞれにデータを挿入します。

CREATE OR REPLACE TABLE dept_pipe_demo (
  deptno NUMBER(2),
  dname VARCHAR(14),
  loc VARCHAR(13)
  ) AS SELECT * FROM VALUES
     (10, 'ACCOUNTING', 'NEW YORK'),
     (20, 'RESEARCH', 'DALLAS'),
     (30, 'SALES', 'CHICAGO'),
     (40, 'OPERATIONS', 'BOSTON');

CREATE OR REPLACE TABLE emp_pipe_demo (
  empno NUMBER(4),
  ename VARCHAR(10),
  sal NUMBER(7,2),
  deptno NUMBER(2)
  ) AS SELECT * FROM VALUES
    (7369, 'SMITH', 800, 20),
    (7499, 'ALLEN', 1600, 30),
    (7521, 'WARD', 1250, 30),
    (7698, 'BLAKE', 2850, 30),
    (7782, 'CLARK', 2450, 10);
Copy

次の例では、 SQL ステートメントのチェーンにパイプ演算子を使用し、以下の操作を実行します。

  1. dnameSALES と等しい行を返すよう、 dept_pipe_demo テーブルをクエリする。

  2. FROM 句の WHERE 条件に $1 を指定することで、前のクエリの結果を入力として使用し、 SALES 部門の給与が 1500 より大きい従業員について、 emp_pipe_demo テーブルをクエリする。

  3. FROM 節に $1 を指定して、前のクエリの結果を入力として enamesal の値を返すクエリを実行する。

SELECT * FROM dept_pipe_demo WHERE dname = 'SALES'
  ->> SELECT * FROM emp_pipe_demo WHERE sal > 1500 AND deptno IN (SELECT deptno FROM $1)
  ->> SELECT ename, sal FROM $1 ORDER BY 2 DESC;
Copy
+-------+---------+
| ENAME |     SAL |
|-------+---------|
| BLAKE | 2850.00 |
| ALLEN | 1600.00 |
+-------+---------+

注釈

この例の目的は、一連のクエリをパイプ演算子で結合する方法を示すことです。しかし、同じ出力は結合クエリで達成することができ、結合クエリは通常、パイプ演算子と組み合わせたクエリよりも優れたパフォーマンスを発揮します。

トランザクションにおける DML 操作の行数を返す

テーブルを作成し、行を1つずつ挿入します。すべてのステートメントを連鎖させることで、パイプ演算子を使って各 INSERT ステートメントの結果を調べることができます。パイプ演算子は、挿入された行の総数を表します。

例のそれぞれの SELECT ステートメントにおいて、 SELECT リストの $1 は、パイプ内の前の結果ではなく、最初の列のショートハンド参照です。パイプ番号のパラメーター $n は、 FROM 句でのみ有効です。

CREATE OR REPLACE TABLE test_sql_pipe_dml (a INT, b INT)
  ->> INSERT INTO test_sql_pipe_dml VALUES (1, 2)
  ->> INSERT INTO test_sql_pipe_dml VALUES (3, 4)
  ->> INSERT INTO test_sql_pipe_dml VALUES (5, 6)
  ->> INSERT INTO test_sql_pipe_dml VALUES (7, 8)
  ->> SELECT (SELECT $1 FROM $4) +
             (SELECT $1 FROM $3) +
             (SELECT $1 FROM $2) +
             (SELECT $1 FROM $1)
        AS "Number of rows";
Copy
+----------------+
| Number of rows |
|----------------|
|              4 |
+----------------+

次の例では、 SQL ステートメントのチェーンにパイプ演算子を使用し、以下の操作を実行します。

  1. トランザクションを開始する。

  2. 先に作成したテーブルに行を挿入する。

  3. テーブルから行を削除する。

  4. テーブルの行を更新する。

  5. トランザクションをコミットする。

  6. 各 DML 操作によって影響を受けた行の数をクエリします。

EXECUTE IMMEDIATE $$
BEGIN TRANSACTION
  ->> INSERT INTO test_sql_pipe_dml VALUES (1, 2)
  ->> DELETE FROM test_sql_pipe_dml WHERE a = 1
  ->> UPDATE test_sql_pipe_dml SET b = 2
  ->> COMMIT
  ->> SELECT
        (SELECT $1 FROM $4) AS "Inserted rows",
        (SELECT $1 FROM $3) AS "Deleted rows",
        (SELECT $1 FROM $2) AS "Updated rows";
$$;
Copy
+---------------+--------------+--------------+
| Inserted rows | Deleted rows | Updated rows |
|---------------+--------------+--------------|
|             1 |            2 |            3 |
+---------------+--------------+--------------+

後で削除されたテーブルへの挿入結果を返します。

この例では、 SQL ステートメントのチェーンにパイプ演算子を使用し、以下の操作を実行します。

  1. IDENTITY 列を持つテーブルを作成する。

  2. テーブルに行を挿入する。

  3. テーブルをクエリする。

  4. テーブルをドロップする。

  5. パイプ番号 $2 (SELECT ステートメント)の結果をクエリする。

最後の SELECT ステートメントで消費された結果セットは、前の SELECT ステートメントのクエリ ID の RESULT_SCAN 関数によって返された結果セットと同等です。

CREATE OR REPLACE TABLE test_sql_pipe_drop (
    id INT IDENTITY START 10 INCREMENT 1,
    data VARCHAR)
  ->> INSERT INTO test_sql_pipe_drop (data) VALUES ('row1'), ('row2'), ('row3')
  ->> SELECT * FROM test_sql_pipe_drop
  ->> DROP TABLE test_sql_pipe_drop
  ->> SELECT COUNT(*) "Number of rows", MAX(id) AS "Last ID" FROM $2;
Copy
+----------------+---------+
| Number of rows | Last ID |
|----------------+---------|
|              3 |      12 |
+----------------+---------+