Categorias:

Funções de tabela

RESULT_SCAN

Retorna o conjunto de resultados de um comando anterior (dentro de 24 horas a partir de quando você executou a consulta) como se o resultado fosse uma tabela. Isto é particularmente útil se você quiser processar a saída de qualquer um dos seguintes itens:

O comando/consulta pode ser da sessão atual ou de qualquer outra sessão, incluindo sessões passadas, desde que o período de 24 horas não tenha transcorrido. Este período não é ajustável. Para obter mais detalhes, consulte Uso de resultados de consultas persistentes.

Consulte também:

DESCRIBE RESULT (DDL de conta e sessão)

Sintaxe

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

Argumentos

query_id ou LAST_QUERY_ID()

Ou a ID para uma consulta executada (dentro das últimas 24 horas em qualquer sessão) ou a função LAST_QUERY_ID, que retorna a ID para uma consulta dentro de sua sessão atual.

Notas de uso

  • Se a consulta original for executada manualmente, somente o usuário que executa a consulta original poderá usar a função RESULT_SCAN para processar a saída da consulta. Mesmo um usuário com privilégio ACCOUNTADMIN não pode acessar os resultados da consulta de outro usuário chamando RESULT_SCAN.

  • Se a consulta original for executada por meio de uma tarefa, a função proprietária da tarefa, em vez de um usuário específico, acionará e executará a consulta. Se um usuário ou tarefa estiver operando com a mesma função, ele poderá usar RESULT_SCAN para acessar os resultados da consulta.

  • O Snowflake armazena todos os resultados das consultas por 24 horas. Esta função só retorna resultados para consultas executadas dentro deste período.

  • Os conjuntos de resultados não têm metadados associado a eles, portanto, o processamento de grandes resultados pode ser mais lento do que se você estivesse consultando uma tabela real.

  • A consulta contendo o RESULT_SCAN pode incluir cláusulas, tais como filtros e cláusulas ORDER BY que não estavam na consulta original. Isso permite reduzir ou modificar o conjunto de resultados.

  • A RESULT_SCAN não garante retornar as linhas na mesma ordem em que a consulta original retornou as linhas. Você pode incluir uma cláusula ORDER BY com a consulta RESULT_SCAN para especificar uma ordem específica.

  • Para recuperar a ID para uma consulta específica, use qualquer um dos seguintes métodos:

    Classic Console

    Em qualquer um dos seguintes locais, clique no link fornecido para exibir/copiar a ID:

    • Em Worksheets Worksheet tab, após executar uma consulta, os resultados incluem um link para a ID.

    • Em History History tab, cada consulta inclui a ID como um link.

    SQL

    Executar uma das seguintes funções:

  • Se RESULT_SCAN processar a saída de consulta que contenha nomes de colunas duplicadas (por exemplo, uma consulta que JOINed duas tabelas que tenham nomes de colunas sobrepostos), então RESULT_SCAN faz referência às colunas duplicadas com nomes modificados, anexando “_1”, “_2” etc. ao nome original. Para obter um exemplo, consulte a seção Exemplos abaixo.

Detalhes do agrupamento

Quando RESULT_SCAN retorna os resultados da instrução anterior, RESULT_SCAN preserva a(s) especificação(ões) de agrupamento dos valores que retorna.

Exemplos

Exemplos simples

Recuperar todos os valores maiores que 1 do resultado de sua consulta mais recente na sessão atual:

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

Recuperar todos os valores de sua segunda consulta mais recente na sessão atual:

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

Recuperar todos os valores de sua primeira consulta na sessão atual:

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

Recuperar os valores da coluna c2 no resultado da consulta especificada:

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

Exemplos usando os comandos DESCRIBE e SHOW

Processar o resultado de um comando DESCRIBE USER para recuperar determinados campos de interesse, por exemplo, a função padrão do usuário. Observe que como os nomes das colunas de saída do comando DESC USER foram gerados em minúsculas, os comandos utilizam notação delimitada do identificador (aspas duplas) em torno dos nomes das colunas na consulta para garantir que os nomes das colunas na consulta correspondam aos nomes das colunas na saída que foi digitalizada.

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

Processe o resultado de um comando SHOW TABLES para extrair tabelas vazias com mais de 21 dias. O comando SHOW gera nomes de colunas em letras minúsculas, então o comando coloca os nomes entre aspas e usa a caixa correspondente:

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

Processe o resultado de um comando SHOW TABLES para extrair as tabelas em ordem decrescente de tamanho. Este exemplo também ilustra o uso de um UDF para mostrar o tamanho da tabela em um formato um pouco mais legível para o ser humano.

-- 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

Exemplos usando um procedimento armazenado

As chamadas de procedimento armazenado retornam um valor. No entanto, este valor não pode ser processado diretamente porque não se pode incorporar uma chamada de procedimento armazenado em outra instrução. Para contornar esta limitação, você pode usar RESULT_SCAN para processar o valor retornado por um procedimento armazenado. Um exemplo simplificado está abaixo:

Primeiro, criar um procedimento que retorna um valor “complicado” (neste caso, uma cadeia de caracteres que contenha dados compatíveis com JSON) que possa ser processado após retornar de CALL.

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

Em segundo lugar, chamar o procedimento:

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

As três etapas seguintes extraem os dados do conjunto de resultados.

Obter a primeira (e única) coluna:

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

Converter a saída de um VARCHAR para uma VARIANT:

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

Extrair o valor que corresponde à chave “keyB”:

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

Esta é uma maneira mais compacta de extrair os mesmos dados que foram extraídos no exemplo anterior. Este exemplo tem menos instruções, mas é mais difícil de ler:

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

A saída do CALL usa o nome da função como o nome da coluna. Por exemplo:

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

Podemos usar esse nome de coluna na consulta. Aqui está uma versão compacta adicional, na qual a coluna é referenciada pelo nome e não pelo número da coluna:

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

Exemplo com nomes de colunas duplicadas

O exemplo a seguir mostra que RESULT_SCAN efetivamente faz referência a nomes de colunas alternativas quando há nomes de colunas duplicadas na consulta original:

Criar duas tabelas que tenham pelo menos uma coluna com o mesmo nome:

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

Carregar os dados nas duas tabelas:

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

Agora executar uma consulta para a qual a saída conterá duas colunas com o mesmo nome:

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

Observe que a saída em Snowsight é diferente da saída mostrada acima, pois Snowsight lida com nomes de coluna duplicados automaticamente.

Agora chame RESULT_SCAN para processar os resultados dessa consulta. Observe que, se houver colunas diferentes com o mesmo nome nos resultados, RESULT_SCAN usa o nome original para a primeira coluna e atribui à segunda coluna um nome modificado que é exclusivo. Para tornar o nome exclusivo, RESULT_SCAN acrescenta o sufixo «_<n>» ao nome, onde «<n>» é o próximo número disponível que produz um nome diferente dos nomes das colunas anteriores.

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