Catégories :

Fonctions de table

RESULT_SCAN

Renvoie l’ensemble de résultats d’une commande précédente (dans les 24 heures suivant l’exécution de la requête) comme si le résultat était une table. Ceci est particulièrement utile si vous souhaitez traiter la sortie provenant de l’un des éléments suivants :

La commande/requête peut provenir de la session en cours ou de l’une de vos autres sessions, y compris les sessions précédentes, tant que la période de 24 heures n’est pas écoulée. Cette période n’est pas réglable. Pour plus de détails, voir Utilisation de résultats de requête persistants.

Voir aussi :

DESCRIBE RESULT (Compte & Session DDL)

Syntaxe

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

Arguments

query_id ou LAST_QUERY_ID()

Soit l’ID d’une requête que vous avez exécutée (dans les dernières 24 heures d’une session quelconque), soit la fonction LAST_QUERY_ID , qui renvoie l’ID d’une requête dans votre session actuelle.

Notes sur l’utilisation

  • Si la requête d’origine est exécutée manuellement, seul l’utilisateur qui exécute la requête d’origine peut utiliser la fonction RESULT_SCAN pour traiter la sortie de la requête. Même un utilisateur disposant du privilège ACCOUNTADMIN ne peut pas accéder aux résultats de la requête d’un autre utilisateur en appelant RESULT_SCAN.

  • Si la requête d’origine est exécutée via une tâche, le rôle propriétaire de la tâche, au lieu d’un utilisateur spécifique, déclenche et exécute la requête. Si un utilisateur ou une tâche fonctionne avec le même rôle, il peut utiliser RESULT_SCAN pour accéder aux résultats de la requête.

  • Snowflake stocke tous les résultats de la requête pendant 24 heures. Cette fonction ne renvoie les résultats que pour les requêtes exécutées durant cette période.

  • Les ensembles de résultats ne sont pas associés à des métadonnées, de sorte que le traitement de résultats volumineux risque d’être plus lent que si vous interrogiez une table réelle.

  • La requête contenant les RESULT_SCAN peut inclure des clauses, telles que des filtres et des clauses ORDER BY, qui ne figuraient pas dans la requête d’origine. Cela vous permet d’affiner ou de modifier le jeu de résultats.

  • Il n’est pas garanti que RESULT_SCAN renvoie des lignes dans le même ordre que la requête d’origine a renvoyé les lignes. Vous pouvez inclure une clause ORDER BY avec la requête RESULT_SCAN pour spécifier un ordre spécifique.

  • Pour récupérer l’ID d’une requête spécifique, utilisez l’une des méthodes suivantes :

    Classic Console:

    Dans l’un des emplacements suivants, cliquez sur le lien fourni pour afficher/copier l’ID :

    • Dans Worksheets Onglet Feuille de calcul, après l’exécution d’une requête, les résultats incluent un lien pour l’ID.

    • Dans History Onglet Historique, chaque requête inclut l’ID en tant que lien.

    SQL:

    Exécutez l’une des fonctions suivantes :

  • Si RESULT_SCAN traite la sortie de la requête qui contenait des noms de colonnes en double (par exemple, une requête qui a joint [ JOINed ] deux tables qui ont des noms de colonnes qui se chevauchent), alors RESULT_SCAN fait référence aux colonnes en double avec des noms modifiés, en ajoutant « _1 » , « _2 », etc. au nom d’origine. (Pour un exemple, voir la section Exemples ci-dessous.)

  • Les horodatages dans les fichiers Parquet interrogés à l’aide du scanner vectorisé affichent parfois l’heure dans un fuseau horaire différent. Utilisez la fonction CONVERT_TIMEZONE pour convertir toutes les données d’horodatage en un fuseau horaire standard.

Détails du classement

Lorsque RESULT_SCAN renvoie les résultats de l’instruction précédente, RESULT_SCAN conserve les spécifications de classement des valeurs renvoyées.

Exemples

Exemples simples

Récupère toutes les valeurs supérieures à 1 du résultat de la dernière requête de la session en cours :

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

Récupère toutes les valeurs de votre deuxième requête la plus récente dans la session en cours :

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

Récupère toutes les valeurs de votre première requête dans la session en cours :

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

Récupère les valeurs de la colonne c2 dans le résultat de la requête spécifiée :

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

Exemples d’utilisation des commandes DESCRIBE et SHOW

Traiter le résultat d’une commande DESCRIBE USER pour récupérer des champs d’intérêt particuliers, par exemple le rôle par défaut de l’utilisateur. Notez que comme les noms des colonnes de sortie de la commande DESC USER ont été générés en minuscules, les commandes utilisent une notation d’identificateur délimitée (guillemets doubles) autour des noms de colonnes dans la requête pour s’assurer que les noms de colonnes dans la requête correspondent aux noms de colonnes dans la sortie qui était analysée.

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

Traiter le résultat d’une commande SHOW TABLES pour extraire les tables vides de plus de 21 jours : La commande SHOW génère des noms de colonnes en minuscules. Elle cite donc les noms et utilise une casse correspondante :

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

Traiter le résultat d’une commande SHOW TABLES pour extraire les tables par ordre décroissant de taille. Cet exemple illustre également l’utilisation d’un UDF pour afficher la taille des tables dans un format légèrement plus lisible pour l’utilisateur.

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

Exemples avec une procédure stockée

Les appels de procédures stockées renvoient une valeur. Toutefois, cette valeur ne peut pas être traitée directement car vous ne pouvez pas incorporer un appel de procédure stockée dans une autre instruction. Pour contourner cette limitation, vous pouvez utiliser RESULT_SCAN pour traiter la valeur renvoyée par une procédure stockée. Voici un exemple simplifié :

Commencez par créer une procédure qui renvoie une valeur « compliquée » (dans ce cas, une chaîne contenant des données compatibles avec JSON) pouvant être traitée après son renvoi depuis CALL.

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

Ensuite, appelez la procédure :

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

Les trois étapes suivantes extraient les données du jeu de résultats.

Obtenez la première (et la seule) colonne :

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

Convertissez le résultat d’un VARCHAR en une VARIANT :

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

Extrayez la valeur qui correspond à la clé « cléB » :

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

Voici un moyen plus compact d’extraire les mêmes données que celles de l’exemple précédent. Cet exemple a moins d’instructions, mais est plus difficile à lire :

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

La sortie de CALL utilise le nom de la fonction comme nom de colonne. Par exemple :

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

Nous pouvons utiliser ce nom de colonne dans la requête. Voici une version compacte supplémentaire dans laquelle la colonne est référencée par son nom plutôt que par son numéro :

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

Exemple avec des noms de colonnes en double

L’exemple suivant montre que RESULT_SCAN fait effectivement référence à d’autres noms de colonne lorsqu’il existe des noms de colonne en double dans la requête d’origine :

Créez deux tables qui ont au moins une colonne du même nom :

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

Chargez les données dans les deux tables :

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

Exécutez maintenant une requête pour laquelle la sortie contiendra deux colonnes du même nom :

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

Notez que la sortie dans Snowsight est différente de la sortie montrée ci-dessus, puisque Snowsight gère automatiquement les noms de colonnes en double.

Appelez maintenant RESULT_SCAN pour traiter les résultats de cette requête. Notez que si différentes colonnes portent le même nom dans les résultats, RESULT_SCAN utilise le nom d’origine pour la première colonne et attribue à la deuxième colonne un nom modifié qui est unique. Pour rendre le nom unique, RESULT_SCAN ajoute le suffixe « _<n> » au nom, où « <n> » est le prochain nombre disponible qui produit un nom différent des noms des colonnes précédentes.

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