Utiliser des requêtes à plusieurs instructions

Ce document explique comment utiliser les requêtes multi-instructions dans BigQuery, en décrivant par exemple l'écriture de requêtes multi-instructions, l'utilisation de tables temporaires dans les requêtes multi-instructions, le référencement de variables dans les requêtes multi-instructions et le débogage de requêtes multi-instructions.

Une requête à plusieurs instructions est un ensemble d'instructions SQL que vous pouvez exécuter dans une seule requête. Avec les requêtes à plusieurs instructions, vous pouvez exécuter plusieurs instructions dans une séquence, avec un état partagé. Les requêtes à plusieurs instructions peuvent avoir des effets secondaires, comme l'ajout ou la modification de données de table.

Les requêtes multi-instructions sont souvent utilisées dans des procédures stockées et acceptent les instructions de langage procédural, qui vous permettent par exemple de définir des variables et de mettre en œuvre un flux de contrôle

Écrire, exécuter et enregistrer des requêtes à plusieurs instructions

Une requête à plusieurs instructions comprend une ou plusieurs instructions SQL séparées par un point-virgule. Toute instruction SQL valide peut être utilisée dans une requête à plusieurs instructions. Les requêtes à plusieurs instructions peuvent également inclure des instructions de langages procéduraux, qui vous permettent d'utiliser des variables ou de mettre en œuvre un flux de contrôle avec vos instructions SQL.

Écrire une requête à plusieurs instructions

Vous pouvez écrire une requête multi-instruction dans BigQuery. La requête multi-instruction suivante déclare une variable et utilise celle-ci dans une instruction IF :

DECLARE day INT64;
SET day = (SELECT EXTRACT(DAYOFWEEK from CURRENT_DATE));
if day = 1 or day = 7 THEN
  SELECT 'Weekend';
ELSE
  SELECT 'Weekday';
END IF

BigQuery interprète toute requête comportant plusieurs instructions comme une requête à plusieurs instructions, sauf si elle est entièrement constituée d'instructions CREATE TEMP FUNCTION suivies d'une seule instruction SELECT. Par exemple, la requête suivante n'est pas considérée comme une requête à plusieurs instructions :

CREATE TEMP FUNCTION Add(x INT64, y INT64) AS (x + y);
SELECT Add(3, 4);

Exécuter une requête multi-instruction

Vous pouvez exécuter une requête à plusieurs instructions de la même manière que toute autre requête, par exemple dans la console Google Cloud ou à l'aide de l'outil de ligne de commande bq.

Simuler une requête à plusieurs instructions

Pour estimer le nombre d'octets lus par une requête à plusieurs instructions, envisagez une simulation. La simulation d'une requête à plusieurs instructions est plus précise pour les requêtes qui ne contiennent que des instructions SELECT.

Les simulations offrent une gestion particulière pour les types de requêtes et d'instructions suivants :

  • Instructions CALL : la simulation vérifie que la procédure appelée existe et possède une signature correspondant aux arguments fournis. Le contenu de la procédure appelée et toutes les instructions après l'instruction CALL ne sont pas validés.
  • Instructions LDD : la simulation valide la première instruction LDD, puis s'arrête. Toutes les instructions suivantes sont ignorées. Les simulations des instructions CREATE TEMP TABLE ne sont pas acceptées.
  • Instructions LMD : la simulation valide l'instruction LMD, puis continue la validation des instructions suivantes. Dans ce cas, les estimations d'octets sont basées sur les tailles de table d'origine et ne tiennent pas compte du résultat de l'instruction LMD.
  • Instructions EXECUTE IMMEDIATE : la simulation valide l'expression de requête, mais n'évalue pas la requête dynamique elle-même. Toutes les instructions qui suivent l'instruction EXECUTE IMMEDIATE sont ignorées.
  • Requêtes utilisant des variables dans un filtre de partitionnement : la simulation valide la requête initiale et les instructions suivantes. Toutefois, la simulation ne peut pas calculer la valeur d'exécution des variables dans un filtre de partition. Cela affecte l'estimation des octets lus.
  • Les requêtes qui utilisent des variables dans l'expression d'horodatage d'une clause FOR SYSTEM TIME AS OF : la simulation utilise le contenu actuel de la table et ignore la clause FOR SYSTEM TIME AS OF. Cela affecte l'estimation des octets lus en cas de différences de taille entre la table actuelle et l'itération précédente de la table.
  • Instructions de contrôle FOR, IF et WHILE : la simulation s'arrête immédiatement. Les expressions de condition, le corps de l'instruction de contrôle et toutes les instructions suivantes ne sont pas validés.

Les simulations fonctionnent de la façon la plus optimale possible et le processus sous-jacent est susceptible d'être modifié. Les simulations sont soumises aux exigences suivantes :

  • Une requête qui effectue une simulation peut ne pas s'exécuter correctement. Par exemple, les requêtes peuvent échouer lors de l'exécution pour des raisons non détectées par les simulations.
  • Une requête qui s'exécute correctement peut ne pas réussir la simulation. Par exemple, les requêtes peuvent échouer lors des simulations en raison de leur interception lors de l'exécution.
  • Il n'est pas garanti que les simulations qui s'exécutent aujourd'hui s'exécutent toujours à l'avenir. Par exemple, les modifications apportées à la mise en œuvre de simulation peuvent détecter des erreurs dans une requête qui n'avaient pas encore été détectées.

Enregistrer une requête multi-instruction

Pour enregistrer une requête à plusieurs instructions, consultez la page Utiliser des requêtes enregistrées.

Utiliser des variables dans une requête multi-instruction

Une requête à plusieurs instructions peut contenir des variables créées par l'utilisateur et des variables système.

  • Vous pouvez déclarer des variables créées par l'utilisateur, leur attribuer des valeurs et les référencer tout au long de la requête.

  • Vous pouvez référencer des variables système dans une requête et attribuer des valeurs à certaines d'entre elles, mais contrairement aux variables définies par l'utilisateur, vous ne les déclarez pas. Les variables système sont intégrées à BigQuery.

Déclarer une variable créée par l'utilisateur

Vous devez déclarer les variables créées par l'utilisateur au début de la requête à plusieurs instructions ou au début d'un bloc BEGIN. Les variables déclarées au début de la requête multi-instruction sont incluses dans le champ d'application pour l'ensemble de la requête. Les variables déclarées dans un bloc BEGIN ont un champ d'application limité au bloc. Elles sont exclues du champ d'application après l'instruction END correspondante. La taille maximale d'une variable est de 1 Mo, et la taille maximale de toutes les variables utilisées dans une requête à plusieurs instructions est de 10 Mo.

Vous pouvez déclarer une variable à l'aide de l'instruction procédurale DECLARE, comme suit :

DECLARE x INT64;

BEGIN
DECLARE y INT64;
-- Here you can reference x and y
END;

-- Here you can reference x, but not y

Définir une variable créée par l'utilisateur

Après avoir déclaré une variable créée par l'utilisateur, vous pouvez lui attribuer une valeur à l'aide de l'instruction procédurale SET, comme suit :

DECLARE x INT64 DEFAULT 0;
SET x = 10;

Définir une variable système

Vous ne créez pas de variables système, mais vous pouvez remplacer la valeur par défaut pour certaines d'entre elles, comme suit :

SET @@dataset_project_id = 'MyProject';

Vous pouvez également définir et utiliser implicitement une variable système dans une requête à plusieurs instructions. Par exemple, dans la requête suivante, vous devez inclure le projet chaque fois que vous souhaitez créer une table :

BEGIN
  CREATE TABLE MyProject.MyDataset.MyTempTableA (id STRING);
  CREATE TABLE MyProject.MyDataset.MyTempTableB (id STRING);
END;

Si vous ne souhaitez pas ajouter le projet aux chemins d'accès aux tables plusieurs fois, vous pouvez attribuer l'ID de projet MyProject à la variable système @@dataset_project_id dans la requête à plusieurs instructions. Cette attribution fait de MyProject le projet par défaut pour le reste de la requête.

SET @@dataset_project_id = 'MyProject';

BEGIN
  CREATE TABLE MyDataset.MyTempTableA (id STRING);
  CREATE TABLE MyDataset.MyTempTableB (id STRING);
END;

De même, vous pouvez définir la variable système @@dataset_id pour attribuer un ensemble de données par défaut à la requête. Par exemple :

SET @@dataset_project_id = 'MyProject';
SET @@dataset_id = 'MyDataset';

BEGIN
  CREATE TABLE MyTempTableA (id STRING);
  CREATE TABLE MyTempTableB (id STRING);
END;

Vous pouvez également référencer explicitement des variables système telles que @@dataset_id dans de nombreuses parties d'une requête à plusieurs instructions. Pour en savoir plus, consultez la section Référencer une variable système.

Référencer une variable créée par l'utilisateur

Une fois que vous avez déclaré et défini une variable créée par l'utilisateur, vous pouvez la référencer dans une requête à plusieurs instructions. Si une variable et une colonne portent le même nom, la colonne est prioritaire.

Cette opération renvoie column x + column x :

DECLARE x INT64 DEFAULT 0;
SET x = 10;

WITH Numbers AS (SELECT 50 AS x)
SELECT (x+x) AS result FROM Numbers;
+--------+
| result |
+--------+
| 100    |
+--------+

Cette opération renvoie column y + variable x :

DECLARE x INT64 DEFAULT 0;
SET x = 10;

WITH Numbers AS (SELECT 50 AS y)
SELECT (y+x) AS result FROM Numbers;
+--------+
| result |
+--------+
| 60     |
+--------+

Référencer une variable système

Vous pouvez référencer une variable système dans une requête à plusieurs instructions.

La requête suivante renvoie le fuseau horaire par défaut :

BEGIN
  SELECT @@time_zone AS default_time_zone;
END;
+-------------------+
| default_time_zone |
+-------------------+
| UTC               |
+-------------------+

Vous pouvez utiliser des variables système avec des requêtes LDD et LMD. Par exemple, voici quelques façons d'utiliser la variable système @@time_zone lors de la création et de la mise à jour d'une table :

BEGIN
  CREATE TEMP TABLE MyTempTable
  AS SELECT @@time_zone AS default_time_zone;
END;
BEGIN
  CREATE OR REPLACE TABLE MyDataset.MyTable(default_time_zone STRING)
  OPTIONS (description = @@time_zone);
END;
BEGIN
  UPDATE MyDataset.MyTable
  SET default_time_zone = @@time_zone
  WHERE TRUE;
END;

Il existe certains cas où les variables système ne peuvent pas être utilisées dans les requêtes LDD et LMD. Par exemple, vous ne pouvez pas utiliser une variable système en tant que nom de projet, ensemble de données ou nom de table. Cela génère une erreur lorsque vous essayez d'inclure la variable système @@dataset_id dans un chemin de table :

BEGIN
  CREATE TEMP TABLE @@dataset_id.MyTempTable (id STRING);
END;

Utiliser des tables temporaires dans une requête multi-instruction

Les tables temporaires vous permettent d'enregistrer les résultats intermédiaires dans une table. Les tables temporaires sont gérées par BigQuery. Vous n'avez donc pas besoin de les enregistrer ni de les conserver dans un ensemble de données. Le stockage de tables temporaires vous est facturé.

Vous pouvez créer et référencer une table temporaire dans une requête multi-instruction. Lorsque vous n'avez plus besoin de la table temporaire, vous pouvez la supprimer manuellement pour réduire les coûts de stockage ou attendre que BigQuery la supprime au bout de 24 heures.

Créer une table temporaire

Vous pouvez créer une table temporaire pour une requête multi-instruction à l'aide de l'instruction CREATE TABLE. L'exemple suivant crée une table temporaire pour stocker les résultats d'une requête et utilise la table temporaire dans une sous-requête :

-- Find the top 100 names from the year 2017.
CREATE TEMP TABLE top_names(name STRING)
AS
 SELECT name
 FROM `bigquery-public-data`.usa_names.usa_1910_current
 WHERE year = 2017
 ORDER BY number DESC LIMIT 100
;
-- Which names appear as words in Shakespeare's plays?
SELECT
 name AS shakespeare_name
FROM top_names
WHERE name IN (
 SELECT word
 FROM `bigquery-public-data`.samples.shakespeare
);

À l'exception de l'utilisation de TEMP ou de TEMPORARY, la syntaxe est identique à la syntaxe CREATE TABLE.

Lorsque vous créez une table temporaire, n'utilisez pas de qualificatif de projet ou d'ensemble de données dans le nom de la table. La table est automatiquement créée dans un ensemble de données spécial.

Référencer une table temporaire

Vous pouvez référencer une table temporaire par son nom pour la durée de la requête à plusieurs instructions en cours. Cela inclut les tables temporaires créées par une procédure au sein de la requête à plusieurs instructions. Vous ne pouvez pas partager des tables temporaires. Les tables temporaires se trouvent dans des ensembles de données _script% masqués, portant des noms générés de manière aléatoire. L'article Répertorier des ensembles de données explique comment répertorier des ensembles de données masqués.

Supprimer des tables temporaires

Vous pouvez supprimer explicitement une table temporaire avant la fin de la requête multi-instruction à l'aide de l'instruction DROP TABLE :

CREATE TEMP TABLE table1(x INT64);
SELECT * FROM table1;  -- Succeeds
DROP TABLE table1;
SELECT * FROM table1;  -- Results in an error

Une fois la requête à plusieurs instructions terminée, la table temporaire peut exister jusqu'à 24 heures.

Afficher les données d'une table temporaire

Après avoir créé une table temporaire, vous pouvez afficher sa structure et les données qu'elle contient. Procédez comme suit pour afficher la structure et les données d'une table :

  1. Dans la console Google Cloud, accédez à la page Explorateur de BigQuery.

    Accéder à l'explorateur

  2. Cliquez sur Historique des requêtes.

  3. Choisissez la requête qui a créé la table temporaire.

  4. Dans la ligne Table de destination, cliquez sur Table temporaire.

Qualifier les tables temporaires avec _SESSION

Lorsque des tables temporaires sont utilisées avec un ensemble de données par défaut, les noms de table non qualifiés font référence à une table temporaire s'il en existe une, ou à une table de l'ensemble de données par défaut. L'exception concerne les instructions CREATE TABLE, où la table cible est considérée comme une table temporaire si et seulement si le mot clé TEMP ou TEMPORARY est présent.

Prenons par exemple la requête à plusieurs instructions suivante :

-- Create table t1 in the default dataset
CREATE TABLE t1 (x INT64);

-- Create temporary table t1.
CREATE TEMP TABLE t1 (x INT64);

-- This statement selects from the temporary table.
SELECT * FROM t1;

-- Drop the temporary table
DROP TABLE t1;

-- Now that the temporary table is dropped, this statement selects from the
-- table in the default dataset.
SELECT * FROM t1;

Vous pouvez indiquer explicitement que vous faites référence à une table temporaire en qualifiant le nom de la table avec _SESSION :

-- Create a temp table
CREATE TEMP TABLE t1 (x INT64);

-- Create a temp table using the `_SESSION` qualifier
CREATE TEMP TABLE _SESSION.t2 (x INT64);

-- Select from a temporary table using the `_SESSION` qualifier
SELECT * FROM _SESSION.t1;

Si vous utilisez le qualificateur _SESSION pour une requête sur une table temporaire qui n'existe pas, la requête à plusieurs instructions génère une erreur indiquant que la table n'existe pas. Par exemple, s'il n'existe aucune table temporaire appelée t3, la requête à plusieurs instructions génère une erreur même si une table nommée t3 existe dans l'ensemble de données par défaut.

Vous ne pouvez pas utiliser _SESSION pour créer une table non-temporaire :

CREATE TABLE _SESSION.t4 (x INT64);  -- Fails

Collecter des informations sur une tâche de requête multi-instruction

Une tâche de requête multi-instruction contient des informations sur la requête multi-instruction qui a été exécutée. Certaines opérations courantes que vous pouvez effectuer avec les données de tâches incluent l'affichage de la dernière instruction exécutée dans la requête multi-instruction, ou l'affichage de toutes les instructions exécutées dans la requête multi-instruction.

Afficher la dernière instruction exécutée

La méthode jobs.getQueryResults affiche les résultats de la dernière instruction exécutée par la requête multi-instructions. Si aucune instruction n'a été exécutée, aucun résultat n'est renvoyé.

Afficher toutes les instructions exécutées

Pour obtenir les résultats de toutes les instructions de la requête multi-instruction, énumérez les tâches enfants et appelez sur chacune d'elles la méthode jobs.getQueryResults.

Énumérer les tâches enfants

Les requêtes à plusieurs instructions sont exécutées dans BigQuery à l'aide de jobs.insert, comme n'importe quelle autre requête, en spécifiant les requêtes à plusieurs instructions comme texte de requête. Lorsqu'une requête à plusieurs instructions s'exécute, des tâches supplémentaires, appelées tâches enfants, sont créées pour chaque instruction de la requête à plusieurs instructions. Vous pouvez répertorier les tâches enfants d'une requête à plusieurs instructions en appelant jobs.list et en transmettant l'ID de tâche de la requête à plusieurs instructions en tant que paramètre parentJobId.

Déboguer une requête à plusieurs instructions

Voici quelques conseils pour déboguer les requêtes à plusieurs instructions :

  • Utilisez l'instruction ASSERT pour confirmer qu'une condition booléenne est "True".

  • Utilisez BEGIN...EXCEPTION...END pour détecter les erreurs et pour afficher le message d'erreur et la trace de la pile.

  • Utilisez SELECT FORMAT("....") pour afficher les résultats intermédiaires.

  • Lorsque vous exécutez une requête à plusieurs instructions dans la console Google Cloud, vous pouvez afficher la sortie de chaque instruction dans la requête à plusieurs instructions. La commande "bq query" de l'outil de ligne de commande affiche également les résultats de chaque étape lorsque vous exécutez une requête à plusieurs instructions.

  • Dans la console Google Cloud, vous pouvez sélectionner une instruction individuelle dans l'éditeur de requête et l'exécuter.

Autorisations

L'autorisation d'accès à une table, un modèle ou une autre ressource est vérifiée au moment de l'exécution. Si une instruction n'est pas exécutée ou qu'une expression n'est pas évaluée, BigQuery ne vérifie pas si l'utilisateur exécutant la requête à plusieurs instructions a accès aux ressources référencées.

Dans une requête à plusieurs instructions, les autorisations de chaque expression ou instruction sont validées séparément. Par exemple :

SELECT * FROM dataset_with_access.table1;
SELECT * FROM dataset_without_access.table2;

Si l'utilisateur exécutant le script a accès à table1, mais pas à table2, la première requête aboutit et la deuxième échoue. La tâche de requête à plusieurs instructions échoue également.

Contraintes de sécurité

Dans les requêtes à plusieurs instructions, vous pouvez utiliser le SQL dynamique pour créer des instructions SQL au moment de l'exécution. Cela est pratique, mais peut offrir de nouvelles opportunités d'utilisation abusive. Par exemple, l'exécution de la requête suivante représente une menace potentielle pour la sécurité (injection SQL), car le paramètre de table peut être mal filtré, autoriser l'accès à et être exécuté sur des tables non souhaitées.

-- Risky query vulnerable to SQL injection attack.
EXECUTE IMMEDIATE CONCAT('SELECT * FROM SensitiveTable WHERE id = ', @id);

Pour éviter d'exposer ou de divulguer des données sensibles dans une table ou d'exécuter des commandes telles que DROP TABLE pour supprimer des données dans une table, les instructions procédurales dynamiques de BigQuery acceptent plusieurs mesures de sécurité pour réduire l'exposition aux attaques d'injection SQL, y compris :

  • Une instruction EXECUTE IMMEDIATE ne permet pas d'intégrer plusieurs instructions SQL à sa requête, développée avec des paramètres et des variables de requête.
  • Les commandes suivantes ne peuvent pas être exécutées dynamiquement : BEGIN/END, CALL, CASE, IF, LOOP, WHILE et EXECUTE IMMEDIATE.

Limites du champ de configuration

Les champs de requête de configuration de tâche suivant ne peuvent pas être définis pour une requête à plusieurs instructions :

  • clustering
  • create_disposition
  • destination_table
  • destination_encryption_configuration
  • range_partitioning
  • schema_update_options
  • time_partitioning
  • user_defined_function_resources
  • write_disposition

Tarifs

La tarification des requêtes multi-instructions inclut les frais liés aux requêtes (lorsque vous utilisez le modèle de facturation à la demande) et le stockage pour les tables temporaires. Lorsque vous utilisez des réservations, l'utilisation des requêtes est couverte par vos frais de réservation.

Calcul de la taille des requêtes à la demande

Si vous utilisez la facturation à la demande, BigQuery facture les requêtes à plusieurs instructions en fonction du nombre d'octets traités lors de l'exécution des requêtes à plusieurs instructions.

Pour obtenir une estimation du nombre d'octets qu'une requête à plusieurs instructions peut traiter, vous pouvez exécuter une simulation.

La tarification suivante s'applique à ces requêtes à plusieurs instructions :

  • DECLARE : nombre total d'octets scannés pour toutes les tables référencées dans l'expression DEFAULT. Les instructions DECLARE sans références de table n'entraînent aucuns frais.

  • SET : nombre total d'octets scannés pour toutes les tables référencées dans l'expression. Les instructions SET sans références de table n'entraînent aucuns frais.

  • IF : nombre total d'octets scannés pour toutes les tables référencées dans l'expression de condition. Les expressions de condition IF sans références de table n'entraînent aucuns frais. Une instruction non exécutée dans le bloc IF n'entraîne aucuns frais.

  • WHILE : nombre total d'octets scannés pour toutes les tables référencées dans l'expression de condition. Les instructions WHILE sans références de table dans l'expression de condition n'entraînent aucuns frais. Une instruction non exécutée dans le bloc WHILE n'entraîne aucuns frais.

  • CONTINUE ou ITERATE : aucuns frais associés.

  • BREAK ou LEAVE : aucuns frais associés.

  • BEGIN ou END : aucuns frais associés.

Si une requête à plusieurs instructions échoue, le coût des instructions effectuées jusqu'au moment de l'échec vous est facturé. Les instructions qui échouent n'entraînent aucuns frais.

Par exemple, l'exemple de code suivant contient des commentaires précédant chaque instruction expliquant le coût, le cas échéant, facturé par chaque instruction :

-- No cost, since no tables are referenced.
DECLARE x DATE DEFAULT CURRENT_DATE();
-- Incurs the cost of scanning string_col from dataset.table.
DECLARE y STRING DEFAULT (SELECT MAX(string_col) FROM dataset.table);
-- Incurs the cost of copying the data from dataset.big_table.  Once the
-- table is created, you are not charged for storage while the rest of the
-- multi-statement query runs.
CREATE TEMP TABLE t AS SELECT * FROM dataset.big_table;
-- Incurs the cost of scanning column1 from temporary table t.
SELECT column1 FROM t;
-- No cost, since y = 'foo' doesn't reference a table.
IF y = 'foo' THEN
  -- Incurs the cost of scanning all columns from dataset.other_table, if
  -- y was equal to 'foo', or otherwise no cost since it is not executed.
  SELECT * FROM dataset.other_table;
ELSE
  -- Incurs the cost of scanning all columns from dataset.different_table, if
  -- y was not equal to 'foo', or otherwise no cost since it is not executed.
  UPDATE dataset.different_table
  SET col = 10
  WHERE true;
END IF;
-- Incurs the cost of scanning date_col from dataset.table for each
-- iteration of the loop.
WHILE x < (SELECT MIN(date_col) FROM dataset.table) DO
  -- No cost, since the expression does not reference any tables.
  SET x = DATE_ADD(x, INTERVAL 1 DAY);
  -- No cost, since the expression does not reference any tables.
  IF true THEN
    -- LEAVE has no associated cost.
    LEAVE;
  END IF;
  -- Never executed, since the IF branch is always taken, so does not incur
  -- a cost.
  SELECT * FROM dataset.big_table;
END WHILE;

Pour en savoir plus, consultez la section Calcul de la taille des requêtes.

Tarifs de stockage

Les tables temporaires créées par des requêtes multi-instructions vous sont facturées. Vous pouvez utiliser les vues TABLE_STORAGE ou TABLE_STORAGE_USAGE_TIMELINE pour afficher l'espace de stockage utilisé par ces tables temporaires. Les tables temporaires se trouvent dans des ensembles de données _script% masqués, portant des noms générés de manière aléatoire.

Quotas

Pour en savoir plus sur les quotas des requêtes à plusieurs instructions, consultez la page Quotas et limites.

Afficher le nombre de requêtes à plusieurs instructions

Vous pouvez afficher le nombre de requêtes à plusieurs instructions actives à l'aide de la vue INFORMATION_SCHEMA.JOBS_BY_PROJECT. L'exemple suivant utilise la vue INFORMATION_SCHEMA.JOBS_BY_PROJECT pour afficher le nombre de requêtes à plusieurs instructions du jour précédent :

SELECT
  COUNT(*)
FROM
  `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT
WHERE
  creation_time BETWEEN TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 DAY) AND CURRENT_TIMESTAMP()
AND job_type = "QUERY"
AND state = 'RUNNING'
AND statement_type = 'SCRIPT'

Pour en savoir plus sur l'interrogation de INFORMATION_SCHEMA.JOBS pour les requêtes à plusieurs instructions, consultez la page Job de requête à plusieurs instruction.