카테고리:

테이블 함수

RESULT_SCAN

결과가 테이블인 것처럼 이전 명령의 결과 세트(쿼리를 실행한 후 24시간 이내)를 반환합니다. 이는 다음 중 하나의 출력을 처리하려는 경우에 특히 유용합니다.

명령/쿼리는 24시간이 경과하지 않는 한, 현재 세션 또는 과거 세션 등 다른 세션에서 가져올 수 있습니다. 이 기간은 조정할 수 없습니다. 자세한 내용은 지속형 쿼리 결과 사용하기 섹션을 참조하십시오.

참고 항목:

DESCRIBE RESULT (계정 및 세션 DDL)

구문

RESULT_SCAN ( { '<query_id>'  | LAST_QUERY_ID() } )
Copy

인자

query_id 또는 LAST_QUERY_ID()

(모든 세션에서 지난 24시간 이내에) 실행한 쿼리의 ID 또는 LAST_QUERY_ID 함수로, 이 함수는 현재 세션 내 쿼리의 ID를 반환합니다.

사용법 노트

  • 원본 쿼리를 수동으로 실행하는 경우 원본 쿼리를 실행하는 사용자만 RESULT_SCAN 함수를 사용하여 쿼리 출력을 처리할 수 있습니다. ACCOUNTADMIN 권한을 가진 사용자라도 RESULT_SCAN을 호출하여 다른 사용자의 쿼리 결과에 액세스할 수 없습니다.

  • 원본 쿼리가 작업 을 통해 실행되는 경우 특정 사용자 대신 작업을 소유한 역할이 쿼리를 트리거하고 실행합니다. 사용자 또는 작업이 동일한 역할로 작업하는 경우 RESULT_SCAN을 사용하여 쿼리 결과에 액세스할 수 있습니다.

  • Snowflake는 모든 쿼리 결과를 24시간 동안 저장합니다. 이 함수는 이 기간 내에 실행된 쿼리에 대한 결과만 반환합니다.

  • 결과 세트에는 연결된 메타데이터가 없으므로 큰 결과를 처리하는 속도는 실제 테이블을 쿼리하는 경우보다 느릴 수 있습니다.

  • RESULT_SCAN을 포함하는 쿼리에는 원래 쿼리에 없던 필터 및 ORDER BY 절 등의 절이 포함될 수 있습니다. 이렇게 하면 결과 세트를 좁히거나 수정할 수 있습니다.

  • RESULT_SCAN은 원래 쿼리에서 행을 반환한 것과 같은 순서로 행을 반환하는 것으로 보장되지 않습니다. 특정 순서를 지정하기 위해 RESULT_SCAN 쿼리와 함께 ORDER BY 절을 포함할 수 있습니다.

  • 특정 쿼리의 ID를 검색하려면 다음 방법 중 하나를 사용하십시오.

    Classic Console

    다음 위치 중 하나에서, 제공된 링크를 클릭하여 ID를 표시/복사합니다.

    • Worksheets Worksheet tab 에서 쿼리를 실행하면 결과에 ID에 대한 링크가 포함됩니다.

    • History History tab 에서 각 쿼리는 ID를 링크로서 포함합니다.

    SQL

    다음 함수 중 하나를 실행합니다.

  • RESULT_SCAN이 중복 열 이름이 포함된 쿼리 출력(예: 겹치는 열 이름이 있는 두 테이블을 조인한 쿼리)을 처리하는 경우, RESULT_SCAN은 수정된 이름을 사용하여 중복 열을 참조하고 원래 이름에 《_1》, 《_2》 등을 추가합니다. 예를 보려면 아래의 섹션을 참조하십시오.

데이터 정렬 세부 정보

RESULT_SCAN 이 이전 문의 결과를 반환할 때 RESULT_SCAN 은 반환하는 값의 데이터 정렬 사양을 유지합니다.

간단한 예

다음과 같이 현재 세션의 가장 최근 쿼리 결과에서 1 보다 큰 모든 값을 검색합니다.

SELECT $1 AS value FROM VALUES (1), (2), (3);

+-------+
| VALUE |
|-------|
|     1 |
|     2 |
|     3 |
+-------+

SELECT * FROM TABLE(RESULT_SCAN(LAST_QUERY_ID())) WHERE value > 1;

+-------+
| VALUE |
|-------|
|     2 |
|     3 |
+-------+
Copy

다음과 같이 현재 세션에서 두 번째로 최근인 쿼리에서 모든 값을 검색합니다.

SELECT * FROM table(RESULT_SCAN(LAST_QUERY_ID(-2)));
Copy

다음과 같이 현재 세션의 첫 번째 쿼리에서 모든 값을 검색합니다.

SELECT * FROM table(RESULT_SCAN(LAST_QUERY_ID(1)));
Copy

다음과 같이 지정된 쿼리 결과의 c2 열에서 값을 검색합니다.

SELECT c2 FROM TABLE(RESULT_SCAN('ce6687a4-331b-4a57-a061-02b2b0f0c17c'));
Copy

DESCRIBE 및 SHOW 명령을 사용한 예

DESCRIBE USER 명령의 결과를 처리하여, 관심 있는 특정 필드(예: 사용자의 기본 역할)를 검색합니다. DESC USER 명령의 출력 열 이름이 소문자로 생성되었기 때문에 명령은 쿼리의 열 이름이 검색된 출력의 열 이름과 일치하도록 쿼리의 열 이름 주위에 구분 식별자 표기법(큰따옴표)을 사용합니다.

DESC USER jessicajones;
SELECT "property", "value" FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()))
  WHERE "property" = 'DEFAULT_ROLE'
  ;
Copy

SHOW TABLES 명령의 결과를 처리하여 21일보다 오래된 빈 테이블을 추출합니다. SHOW 명령은 소문자 열 이름을 생성하므로, 이 명령은 이름을 따옴표로 묶고 일치하는 대/소문자를 사용합니다.

SHOW TABLES;
-- Show the tables that are more than 21 days old and that are empty
-- (i.e. tables that I might have forgotten about).
SELECT "database_name", "schema_name", "name" as "table_name", "rows", "created_on"
    FROM table(RESULT_SCAN(LAST_QUERY_ID()))
    WHERE "rows" = 0 AND "created_on" < DATEADD(day, -21, CURRENT_TIMESTAMP())
    ORDER BY "created_on";
Copy

SHOW TABLES 명령의 결과를 처리하여 크기의 내림차순으로 테이블을 추출합니다. 이 예에서는 UDF를 사용하여, 사람이 읽기에 약간 더 편한 형식으로 테이블 크기를 표시하는 방법도 보여줍니다.

-- Show byte counts with suffixes such as "KB", "MB", and "GB".
CREATE OR REPLACE FUNCTION NiceBytes(NUMBER_OF_BYTES INTEGER)
RETURNS VARCHAR
AS
$$
CASE
    WHEN NUMBER_OF_BYTES < 1024
        THEN NUMBER_OF_BYTES::VARCHAR
    WHEN NUMBER_OF_BYTES >= 1024 AND NUMBER_OF_BYTES < 1048576
        THEN (NUMBER_OF_BYTES / 1024)::VARCHAR || 'KB'
   WHEN NUMBER_OF_BYTES >= 1048576 AND NUMBER_OF_BYTES < (POW(2, 30))
       THEN (NUMBER_OF_BYTES / 1048576)::VARCHAR || 'MB'
    ELSE
        (NUMBER_OF_BYTES / POW(2, 30))::VARCHAR || 'GB'
END
$$
;
SHOW TABLES;
-- Show all of my tables in descending order of size.
SELECT "database_name", "schema_name", "name" as "table_name", NiceBytes("bytes") AS "size"
    FROM table(RESULT_SCAN(LAST_QUERY_ID()))
    ORDER BY "bytes" DESC;
Copy

저장 프로시저를 사용한 예

저장 프로시저 호출은 값을 반환합니다. 그러나 다른 문에 저장 프로시저 호출을 포함할 수 없기 때문에 이 값은 직접 처리될 수 없습니다. 이 제한을 해결하기 위해 RESULT_SCAN 을 사용하여 저장 프로시저에서 반환된 값을 처리할 수 있습니다. 단순화된 예는 다음과 같습니다.

먼저, CALL 에서 반환된 후 처리할 수 있는 《복잡한》 값(이 경우, JSON 호환 데이터가 포함된 문자열)을 반환하는 프로시저를 만듭니다.

CREATE OR REPLACE PROCEDURE return_JSON()
    RETURNS VARCHAR
    LANGUAGE JavaScript
    AS
    $$
        return '{"keyA": "ValueA", "keyB": "ValueB"}';
    $$
    ;
Copy

둘째, 다음과 같이 프로시저를 호출합니다.

CALL return_JSON();
+--------------------------------------+
| RETURN_JSON                          |
|--------------------------------------|
| {"keyA": "ValueA", "keyB": "ValueB"} |
+--------------------------------------+
Copy

다음 세 단계는 결과 세트에서 데이터를 추출합니다.

다음과 같이 첫 번째(그리고 유일한) 열을 가져옵니다.

SELECT $1 AS output_col FROM table(RESULT_SCAN(LAST_QUERY_ID()));
+--------------------------------------+
| OUTPUT_COL                           |
|--------------------------------------|
| {"keyA": "ValueA", "keyB": "ValueB"} |
+--------------------------------------+
Copy

다음과 같이 VARCHAR의 출력을 VARIANT로 변환합니다.

SELECT PARSE_JSON(output_col) AS JSON_COL FROM table(RESULT_SCAN(LAST_QUERY_ID()));
+---------------------+
| JSON_COL            |
|---------------------|
| {                   |
|   "keyA": "ValueA", |
|   "keyB": "ValueB"  |
| }                   |
+---------------------+
Copy

다음과 같이 키 《keyB》에 해당하는 값을 추출합니다.

SELECT JSON_COL:keyB FROM table(RESULT_SCAN(LAST_QUERY_ID()));
+---------------+
| JSON_COL:KEYB |
|---------------|
| "ValueB"      |
+---------------+
Copy

다음은 이전 예에서 추출한 것과 동일한 데이터를 추출하는 더 간결한 방법입니다. 이 예에는 문이 더 적지만, 읽기가 더 어렵습니다.

CALL return_JSON();
+--------------------------------------+
| RETURN_JSON                          |
|--------------------------------------|
| {"keyA": "ValueA", "keyB": "ValueB"} |
+--------------------------------------+
SELECT JSON_COL:keyB 
   FROM (
        SELECT PARSE_JSON($1::VARIANT) AS JSON_COL 
            FROM table(RESULT_SCAN(LAST_QUERY_ID()))
        );
+---------------+
| JSON_COL:KEYB |
|---------------|
| "ValueB"      |
+---------------+
Copy

CALL의 출력은 함수 이름을 열 이름으로 사용합니다. 예:

+--------------------------------------+
|              RETURN_JSON             |
+--------------------------------------+
| {"keyA": "ValueA", "keyB": "ValueB"} |
+--------------------------------------+
Copy

쿼리에서 해당 열 이름을 사용할 수 있습니다. 다음은 열이 열 번호가 아닌 이름으로 참조되는 추가적인 간결한 버전입니다.

CALL return_JSON();
+--------------------------------------+
| RETURN_JSON                          |
|--------------------------------------|
| {"keyA": "ValueA", "keyB": "ValueB"} |
+--------------------------------------+
SELECT JSON_COL:keyB
        FROM (
             SELECT PARSE_JSON(RETURN_JSON::VARIANT) AS JSON_COL 
                 FROM table(RESULT_SCAN(LAST_QUERY_ID()))
             );
+---------------+
| JSON_COL:KEYB |
|---------------|
| "ValueB"      |
+---------------+
Copy

중복 열 이름이 있는 예

다음 예에서는 원래 쿼리에 중복 열 이름이 있는 경우 RESULT_SCAN이 대체 열 이름을 효과적으로 참조함을 보여줍니다.

이름이 같은 열이 하나 이상 있는 두 개의 테이블을 다음과 같이 만듭니다.

CREATE TABLE employees (id INT);
Copy
CREATE TABLE dependents (id INT, employee_id INT);
Copy

다음과 같이 이 두 테이블에 데이터를 로딩합니다.

INSERT INTO employees (id) VALUES (11);
Copy
INSERT INTO dependents (id, employee_id) VALUES (101, 11);
Copy

이제 동일한 이름을 가진 두 개의 열이 출력에 포함될 쿼리를 다음과 같이 실행합니다.

SELECT * 
    FROM employees INNER JOIN dependents
        ON dependents.employee_ID = employees.id
    ORDER BY employees.id, dependents.id
    ;
+----+-----+-------------+
| ID |  ID | EMPLOYEE_ID |
|----+-----+-------------|
| 11 | 101 |          11 |
+----+-----+-------------+
Copy

Snowsight 는 중복 열 이름을 자동으로 처리하므로 Snowsight 의 출력은 위에 표시된 출력과는 다릅니다.

이제 RESULT_SCAN을 호출하여 해당 쿼리의 결과를 처리합니다. 결과에 같은 이름을 가진 서로 다른 열이 있는 경우 RESULT_SCAN은 첫 번째 열에 원래 이름을 사용하고 두 번째 열에 고유한 수정된 이름을 지정합니다. 이름을 고유하게 만들기 위해 RESULT_SCAN은 이름에 접미사 《_<n>》을 추가하는데, 여기서 《<n>》은 이전 열의 이름과는 다른 이름을 생성하는 다음으로 사용 가능한 숫자입니다.

SELECT id, id_1, employee_id
    FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()))
    WHERE id_1 = 101;
+----+------+-------------+
| ID | ID_1 | EMPLOYEE_ID |
|----+------+-------------|
| 11 |  101 |          11 |
+----+------+-------------+
Copy