흐름 연산자

흐름 연산자는 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 문은 세 개의 SELECT 문에 파이프 번호 참조가 있으며, 각 문은 첫 번째 SELECT 문의 결과를 입력으로 받습니다.

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

표시된 것처럼 마지막 문 뒤에 세미콜론을 배치하여 SQL 문의 체인을 종료합니다. 체인에서 이전 문 뒤에 세미콜론을 넣지 마십시오. 전체 체인의 출력은 마지막 SQL 문의 최종 결과입니다. SnowSQL 과 같은 클라이언트 도구는 일련의 문을 하나의 문으로 취급합니다.

파이프 연산자는 다음과 같은 이점을 제공합니다.

  • 종속 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_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;
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. dept_pipe_demo 테이블을 쿼리하여 dnameSALES 와 같은 행을 반환합니다.

  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 작업에 대한 행 수 반환하기

테이블을 만들고 행을 하나씩 삽입합니다. 모든 문을 연결하면 파이프 연산자를 사용하여 삽입된 총 행 수를 나타내는 각 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 |
+----------------+---------+