흐름 연산자¶
흐름 연산자는 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;
예를 들어, 이 일련의 SQL 문은 세 개의 SELECT 문에 파이프 번호 참조가 있으며, 각 문은 첫 번째 SELECT 문의 결과를 입력으로 받습니다.
SELECT ...
  ->> SELECT ... FROM $1
  ->> SELECT ... FROM $2
  ->> SELECT ... FROM $3;
표시된 것처럼 마지막 문 뒤에 세미콜론을 배치하여 SQL 문의 체인을 종료합니다. 체인에서 이전 문 뒤에 세미콜론을 넣지 마십시오. 전체 체인의 출력은 마지막 SQL 문의 최종 결과입니다. SnowSQL 과 같은 클라이언트 도구는 일련의 문을 하나의 문으로 취급합니다.
파이프 연산자는 다음과 같은 이점을 제공합니다.
- 종속 SQL 문의 실행을 단순화합니다. 
- 복잡한 SQL 작업의 가독성과 유연성을 개선합니다. 
구문¶
<sql_statement_1> ->> <sql_statement_2> [ ->> <sql_statement_n> ... ]
사용법 노트¶
- 각 문은 체인의 후속 문에 의해서만 소비될 수 있는 결과를 생성합니다. 
- 문은 지정된 순서대로 실행됩니다. - 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))); - 이 문은 파이프 연산자를 사용하여 동일한 결과를 생성합니다. - SHOW WAREHOUSES ->> SELECT "name", "state", "type", "size" FROM $1; - SHOW 및 DESCRIBE 명령의 출력 열 이름은 소문자로 생성됩니다. 파이프 연산자 또는 RESULT_SCAN 함수와 함께 SHOW 또는 DESCRIBE 명령의 결과 세트를 사용하는 경우 쿼리의 열 이름에 큰따옴표로 묶인 식별자 를 사용하여 스캔된 출력의 열 이름과 일치하도록 합니다. 예를 들어, 출력 열의 이름이 - type인 경우 식별자에 대해- "type"을 지정합니다.
- 파이프 연산자를 사용하는 쿼리는 체인에서 이전 쿼리의 입력 결과 세트와 동일한 순서로 행을 반환하는 것이 보장되지 않습니다. 순서를 지정하기 위해 쿼리와 함께 ORDER BY 절을 포함할 수 있습니다. 
- SQL 문에 의해 오류가 발생하면 체인 실행이 중지되고 해당 오류는 클라이언트에 반환됩니다. 
- 마지막 문 결과가 클라이언트에 반환됩니다. 
- 문은 Snowflake Scripting 익명 블록으로 실행됩니다. 
제한 사항¶
- $n매개 변수는 SQL 문의 FROM 절에서만 유효합니다.
- 각 SQL 문은 파이프 체인의 후속 문에 의해서만 소비될 수 있는 결과를 생성합니다. 결과는 마지막 문의 결과를 제외하고는 파이프 체인 외부에서 소비할 수 없습니다. 
- 바인드 변수는 지원되지 않습니다. 
- Snowflake 클라이언트 드라이버에서 다중 문 실행에 파이프 연산자를 사용하는 것은 지원되지 않습니다(즉, 단일 호출에서 - ->>가 아닌- ;으로 구분된 여러 문 제출).
- :doc:`Snowflake Scripting</developer-guide/snowflake-scripting/index>`에서 파이프 연산자를 사용하는 경우 SQL 문에서 파이프 연산자를 사용하면 RESULTSET의 선언과 할당을 결합할 수 없습니다. - 예를 들어, 다음 쿼리는 오류를 반환합니다. - LET res RESULTSET := (SELECT 'myvalue' ->> SELECT $1 FROM $1); RETURN TABLE(res); - 다음 예는 RESULTSET의 선언과 할당을 분리하므로 성공합니다. - LET res RESULTSET; res := (SELECT 'myvalue' ->> SELECT $1 FROM $1); RETURN TABLE(res); 
예¶
다음 예제에서는 파이프 연산자를 사용합니다.
SHOW 명령의 출력을 위한 열 목록 선택하기¶
SHOW TABLES 명령을 실행하고 파이프 연산자를 사용하여 2025년 4월 15일 이후에 생성된 테이블의 created_on, name, owner 열로 출력을 제한합니다.
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;
+-------------------------------+-------------+--------------+
| 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);
다음 예제에서는 다음 작업을 수행하는 SQL 문의 체인에 파이프 연산자를 사용합니다.
- dept_pipe_demo테이블을 쿼리하여- dname이- SALES와 같은 행을 반환합니다.
- FROM 절의 WHERE 조건에 - $1을 지정하여 이전 쿼리 결과를 입력으로 사용하여- SALES부서에서 급여가- 1500보다 많은 직원에 대해- emp_pipe_demo테이블을 쿼리합니다.
- FROM 절에 - $1을 지정하여 이전 쿼리 결과를 입력으로 사용하여- ename및- sal값을 반환하는 쿼리를 실행합니다.
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;
+-------+---------+
| ENAME |     SAL |
|-------+---------|
| BLAKE | 2850.00 |
| ALLEN | 1600.00 |
+-------+---------+
참고
이 예제의 목적은 일련의 쿼리를 파이프 연산자와 결합하는 방법을 보여주기 위한 것입니다. 그러나 조인 쿼리로도 동일한 출력을 얻을 수 있으며, 일반적으로 조인 쿼리는 파이프 연산자와 결합된 쿼리보다 성능이 더 우수합니다.
트랜잭션에서 DML 작업에 대한 행 수 반환하기¶
테이블을 만들고 행을 하나씩 삽입합니다. 모든 문을 연결하면 파이프 연산자를 사용하여 삽입된 총 행 수를 나타내는 각 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";
+----------------+
| Number of rows |
|----------------|
|              4 |
+----------------+
다음 예제에서는 다음 작업을 수행하는 SQL 문의 체인에 파이프 연산자를 사용합니다.
- 트랜잭션을 시작합니다. 
- 이전에 생성한 테이블에 행을 삽입합니다. 
- 테이블에서 행을 삭제합니다. 
- 테이블의 행을 업데이트합니다. 
- 트랜잭션을 커밋합니다. 
- 각 DML 작업의 영향을 받은 행 수를 쿼리합니다. 
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";
+---------------+--------------+--------------+
| Inserted rows | Deleted rows | Updated rows |
|---------------+--------------+--------------|
|             1 |            2 |            3 |
+---------------+--------------+--------------+
나중에 제거된 테이블에 삽입한 결과 반환하기¶
이 예에서는 다음 작업을 수행하는 SQL 문의 체인에 파이프 연산자를 사용합니다.
- IDENTITY 열이 있는 테이블을 만듭니다. 
- 테이블에 행을 삽입합니다. 
- 테이블을 쿼리합니다. 
- 테이블을 삭제합니다. 
- 파이프 번호 - $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;
+----------------+---------+
| Number of rows | Last ID |
|----------------+---------|
|              3 |      12 |
+----------------+---------+