Utilizzare query con più istruzioni
Una query con più istruzioni è una raccolta di istruzioni SQL che puoi eseguire in sequenza, con uno stato condiviso.
Questo documento descrive come utilizzare le query multi-istruzione in BigQuery, ad esempio come scrivere query multi-istruzione, utilizzare tabelle temporanee nelle query multi-istruzione, fare riferimento a variabili nelle query multi-istruzione ed eseguire il debug delle query multi-istruzione.
Le query con più istruzioni vengono spesso utilizzate nelle stored procedure e supportano istruzioni di linguaggio procedurale, che ti consentono di definire variabili e implementare il flusso di controllo. Le query con più istruzioni possono contenere istruzioni DDL e DML che hanno effetti collaterali, ad esempio la creazione o la modifica di tabelle o dati delle tabelle.
Scrivere, eseguire e salvare query multi-istruzione
Una query multi-istruzione è costituita da una o più istruzioni SQL separate da punti e virgola. In una query con più istruzioni può essere utilizzata qualsiasi istruzione SQL valida. Le query con più istruzioni possono includere anche istruzioni del linguaggio procedurale, che consentono di utilizzare variabili o implementare il flusso di controllo con le istruzioni SQL.
Scrivere una query con più istruzioni
Puoi scrivere una query con più istruzioni in BigQuery. La seguente query
con più istruzioni dichiara una variabile e la utilizza
all'interno di un'istruzione 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 interpreta qualsiasi richiesta con più istruzioni come una query con più istruzioni, a meno che le istruzioni non siano costituite interamente da istruzioni CREATE TEMP FUNCTION
seguite da una singola istruzione SELECT
.
Ad esempio, la seguente non è considerata una query con più istruzioni:
CREATE TEMP FUNCTION Add(x INT64, y INT64) AS (x + y);
SELECT Add(3, 4);
Eseguire una query con più istruzioni
Puoi eseguire una query con più istruzioni nello stesso modo di qualsiasi altra query, ad esempio nella console Trusted Cloud o utilizzando lo strumento a riga di comando bq.
Eseguire una prova di una query con più istruzioni
Per stimare il numero di byte letti da una query con più istruzioni, prendi in considerazione un
test dry run. L'esecuzione di prova di una
query con più istruzioni è più precisa per le query che contengono solo istruzioni SELECT
.
Le prove dry run hanno una gestione speciale per i seguenti tipi di query e istruzioni:
- Istruzioni
CALL
: la prova dry run verifica che la procedura chiamata esista e abbia una firma corrispondente agli argomenti forniti. Il contenuto della procedura chiamata e tutte le istruzioni dopo l'istruzioneCALL
non vengono convalidate. - Istruzioni DDL:
la prova dry run convalida la prima istruzione DDL e poi
si interrompe. Tutte le istruzioni successive vengono ignorate. Le prove generali delle istruzioni
CREATE TEMP TABLE
non sono supportate. - Istruzioni DML: la prova dry run convalida l'istruzione DML e poi continua a convalidare le istruzioni successive. In questo caso, le stime dei byte si basano sulle dimensioni originali delle tabelle e non tengono conto del risultato dell'istruzione DML.
EXECUTE IMMEDIATE
istruzioni: la prova generale convalida l'espressione di query, ma non valuta la query dinamica stessa. Tutte le istruzioni successive all'istruzioneEXECUTE IMMEDIATE
vengono ignorate.- Query che utilizzano variabili in un filtro di partizionamento: l'esecuzione di prova convalida la query iniziale e le istruzioni successive. Tuttavia, la prova non è in grado di calcolare il valore di runtime delle variabili in un filtro di partizione. Ciò influisce sulla stima dei byte letti.
- Query che utilizzano variabili nell'espressione timestamp di una clausola
FOR SYSTEM TIME AS OF
: l'esecuzione di prova utilizza i contenuti attuali della tabella e ignora la clausolaFOR SYSTEM TIME AS OF
. Ciò influisce sulla stima dei byte letti se ci sono differenze di dimensioni tra la tabella attuale e l'iterazione precedente della tabella. - I controlli
FOR
,IF
eWHILE
: il test di prova si interrompe immediatamente. Le espressioni delle condizioni, i corpi dell'istruzione di controllo e tutte le istruzioni successive non vengono convalidate.
Le prove generali vengono eseguite al meglio delle possibilità e il processo sottostante è soggetto a modifiche. Le prove dry run sono soggette alle seguenti condizioni:
- Una query che completa correttamente una prova potrebbe non essere eseguita correttamente. Ad esempio, le query potrebbero non riuscire in fase di runtime per motivi non rilevati dalle prove.
- Una query eseguita correttamente potrebbe non completare correttamente una prova. Ad esempio, le query potrebbero non superare le prove a causa di motivi rilevati durante l'esecuzione.
- Non è garantito che le prove eseguite correttamente oggi vengano eseguite sempre in futuro. Ad esempio, le modifiche all'implementazione della prova generale potrebbero rilevare errori in una query che in precedenza non erano stati rilevati.
Salvare una query multi-statement
Per salvare una query con più istruzioni, consulta la sezione Utilizzare le query salvate.
Utilizzare le variabili in una query con più istruzioni
Una query con più istruzioni può contenere variabili create dall'utente e variabili di sistema.
Puoi dichiarare le variabili create dall'utente, assegnare loro valori e farvi riferimento in tutta la query.
Puoi fare riferimento alle variabili di sistema in una query e assegnare valori ad alcune di queste, ma a differenza delle variabili definite dall'utente, non le dichiari. Le variabili di sistema sono integrate in BigQuery.
Dichiarare una variabile creata dall'utente
Devi dichiarare le variabili create dall'utente all'inizio della query con più istruzioni o all'inizio di un blocco BEGIN
. Le variabili dichiarate all'inizio della query multi-istruzione sono nell'ambito
dell'intera query. Le variabili dichiarate all'interno di un blocco BEGIN
hanno ambito per il blocco. Vengono esclusi dall'ambito dopo l'estratto conto END
corrispondente. La
dimensione massima di una variabile è 1 MB e la dimensione massima di tutte le variabili utilizzate
in una query con più istruzioni è 10 MB.
Puoi dichiarare una variabile con l'istruzione procedurale
DECLARE
come segue:
DECLARE x INT64;
BEGIN
DECLARE y INT64;
-- Here you can reference x and y
END;
-- Here you can reference x, but not y
Impostare una variabile creata dall'utente
Dopo aver dichiarato una variabile creata dall'utente, puoi assegnarle un valore con l'istruzione procedurale
SET
come segue:
DECLARE x INT64 DEFAULT 0;
SET x = 10;
Impostare una variabile di sistema
Non crei variabili di sistema, ma puoi sostituire il valore predefinito di alcune di queste nel seguente modo:
SET @@dataset_project_id = 'MyProject';
Puoi anche impostare e utilizzare implicitamente una variabile di sistema in una query con più istruzioni. Ad esempio, nella seguente query devi includere il progetto ogni volta che vuoi creare una nuova tabella:
BEGIN
CREATE TABLE MyProject.MyDataset.MyTempTableA (id STRING);
CREATE TABLE MyProject.MyDataset.MyTempTableB (id STRING);
END;
Se non vuoi aggiungere il progetto ai percorsi delle tabelle più volte, puoi
assegnare l'ID progetto del set di dati MyProject
alla variabile di sistema @@dataset_project_id
nella query con più istruzioni. Questa assegnazione rende MyProject
il progetto predefinito per il resto della query.
SET @@dataset_project_id = 'MyProject';
BEGIN
CREATE TABLE MyDataset.MyTempTableA (id STRING);
CREATE TABLE MyDataset.MyTempTableB (id STRING);
END;
Allo stesso modo, puoi impostare la variabile di sistema @@dataset_id
per assegnare un set di dati predefinito alla query. Ad esempio:
SET @@dataset_project_id = 'MyProject';
SET @@dataset_id = 'MyDataset';
BEGIN
CREATE TABLE MyTempTableA (id STRING);
CREATE TABLE MyTempTableB (id STRING);
END;
Puoi anche fare riferimento esplicito a variabili di sistema come @@dataset_id
in
molte parti di una query con più istruzioni. Per saperne di più, consulta gli
esempi di variabili di sistema.
Fare riferimento a una variabile creata dall'utente
Dopo aver dichiarato e impostato una variabile creata dall'utente, puoi farvi riferimento in una query con più istruzioni. Se una variabile e una colonna condividono lo stesso nome, la colonna ha la precedenza.
Restituisce 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 |
+--------+
Viene restituito 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 |
+--------+
Utilizzare tabelle temporanee in una query con più istruzioni
Le tabelle temporanee consentono di salvare i risultati intermedi in una tabella. Le tabelle temporanee sono gestite da BigQuery, quindi non devi salvarle o gestirle in un set di dati. Ti viene addebitato il costo dell'archiviazione delle tabelle temporanee.
Puoi creare e fare riferimento a una tabella temporanea in una query con più istruzioni. Al termine dell'utilizzo della tabella temporanea, puoi eliminarla manualmente per ridurre al minimo i costi di archiviazione oppure attendere che BigQuery la elimini dopo 24 ore.
Crea una tabella temporanea
Puoi creare una tabella temporanea per una query con più istruzioni con l'istruzione
CREATE TABLE
.
L'esempio seguente crea una tabella temporanea per archiviare i risultati di una query
e utilizza la tabella temporanea in una sottoquery:
-- 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
);
A parte l'utilizzo di TEMP
o TEMPORARY
, la sintassi è identica a quella di
CREATE TABLE
.
Quando crei una tabella temporanea, non utilizzare un qualificatore di progetto o set di dati nel nome della tabella. La tabella viene creata automaticamente in un set di dati speciale.
Fare riferimento a una tabella temporanea
Puoi fare riferimento a una tabella temporanea per nome per la durata della query
multi-istruzione corrente. Sono incluse le tabelle temporanee create da una procedura
all'interno della query multi-istruzione. Non puoi condividere le tabelle temporanee. Le tabelle temporanee si trovano in set di dati _script%
nascosti con nomi generati in modo casuale.
L'articolo Elenco dei set di dati descrive come elencare i set di dati nascosti.
Elimina le tabelle temporanee
Puoi eliminare una tabella temporanea in modo esplicito prima del completamento della query multi-istruzione
utilizzando l'istruzione DROP TABLE
:
CREATE TEMP TABLE table1(x INT64); SELECT * FROM table1; -- Succeeds DROP TABLE table1; SELECT * FROM table1; -- Results in an error
Al termine di una query con più istruzioni, la tabella temporanea esiste per un massimo di 24 ore.
Visualizzare i dati della tabella temporanea
Dopo aver creato una tabella temporanea, puoi visualizzarne la struttura e i dati. Per visualizzare la struttura e i dati della tabella, segui questi passaggi:
Nella console Trusted Cloud , vai alla pagina Explorer di BigQuery.
Fai clic su Cronologia query.
Scegli la query che ha creato la tabella temporanea.
Nella riga Tabella di destinazione, fai clic su Tabella temporanea.
Qualifica le tabelle temporanee con _SESSION
Quando le tabelle temporanee vengono utilizzate insieme a un set di dati predefinito, i nomi delle tabelle non qualificati fanno riferimento a una tabella temporanea, se esiste, o a una tabella nel set di dati predefinito. L'eccezione riguarda le istruzioni CREATE TABLE
, in cui la tabella di destinazione
è considerata una tabella temporanea se e solo se è presente la parola chiave TEMP
o TEMPORARY
.
Ad esempio, considera la seguente query con più istruzioni:
-- 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;
Puoi indicare esplicitamente che ti riferisci a una tabella temporanea qualificando il nome della tabella con _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;
Se utilizzi il qualificatore _SESSION
per una query di una tabella temporanea che non esiste, la query multi-istruzione genera un errore che indica che la tabella non esiste. Ad esempio, se non esiste una tabella temporanea denominata t3
, la
query multi-istruzione genera un errore anche se esiste una tabella denominata t3
nel
set di dati predefinito.
Non puoi utilizzare _SESSION
per creare una tabella non temporanea:
CREATE TABLE _SESSION.t4 (x INT64); -- Fails
Raccogliere informazioni su un job di query multi-istruzione
Un job di query con più istruzioni contiene informazioni su una query con più istruzioni che è stata eseguita. Alcune attività comuni che puoi eseguire con i dati dei job includono la restituzione dell'ultima istruzione eseguita con la query multi-istruzione o la restituzione di tutte le istruzioni eseguite con la query multi-istruzione.
Restituisce l'ultima istruzione eseguita
Il metodo jobs.getQueryResults
restituisce i risultati della query per l'ultima istruzione da eseguire nella query con più istruzioni. Se non è stata eseguita alcuna istruzione, non vengono restituiti risultati.
Restituisci tutte le istruzioni eseguite
Per ottenere i risultati di tutte le istruzioni in una
query con più istruzioni, enumera i job secondari
e chiama jobs.getQueryResults
per ognuno.
Enumerare i job secondari
Le query con più istruzioni vengono eseguite in BigQuery utilizzando
jobs.insert
,
in modo simile a qualsiasi altra query, con le query con più istruzioni specificate come
testo della query. Quando viene eseguita una query con più istruzioni, vengono creati job aggiuntivi, noti come
job secondari, per ogni istruzione nella query con più istruzioni. Puoi
enumerare i job secondari di una query multi-istruzione chiamando
jobs.list
, passando l'ID job della
query multi-istruzione come parametro parentJobId
.
Eseguire il debug di una query con più istruzioni
Ecco alcuni suggerimenti per il debug delle query con più istruzioni:
Utilizza l'istruzione
ASSERT
per verificare che una condizione booleana sia vera.Utilizza
BEGIN...EXCEPTION...END
per rilevare gli errori e visualizzare il messaggio di errore e analisi dello stack.Utilizza
SELECT FORMAT("....")
per mostrare i risultati intermedi.Quando esegui una query con più istruzioni nella console Trusted Cloud , puoi visualizzare l'output di ogni istruzione nella query con più istruzioni. Il comando
bq query
dello strumento a riga di comando bq mostra anche i risultati di ogni passaggio quando esegui una query con più istruzioni.Nella console Trusted Cloud , puoi selezionare una singola istruzione all'interno dell'editor di query ed eseguirla.
Autorizzazioni
L'autorizzazione per accedere a una tabella, a un modello o a un'altra risorsa viene verificata al momento dell'esecuzione. Se un'istruzione non viene eseguita o un'espressione non viene valutata, BigQuery non controlla se l'utente che esegue la query multi-istruzione ha accesso a eventuali risorse a cui fa riferimento.
All'interno di una query con più istruzioni, le autorizzazioni per ogni espressione o istruzione vengono convalidate separatamente. Ad esempio:
SELECT * FROM dataset_with_access.table1; SELECT * FROM dataset_without_access.table2;
Se l'utente che esegue la query ha accesso a table1
ma non a table2
, la prima query ha esito positivo e la
seconda query ha esito negativo. Anche il job di query con più istruzioni non va a buon fine.
Vincoli di sicurezza
Nelle query con più istruzioni, puoi utilizzare SQL dinamico per creare istruzioni SQL in fase di runtime. È una soluzione comoda, ma può offrire nuove opportunità di uso improprio. Ad esempio, l'esecuzione della seguente query pone una potenziale minaccia alla sicurezza di SQL injection, poiché il parametro della tabella potrebbe essere filtrato in modo improprio, consentire l'accesso ed essere eseguito su tabelle non previste.
-- Risky query vulnerable to SQL injection attack.
EXECUTE IMMEDIATE CONCAT('SELECT * FROM SensitiveTable WHERE id = ', @id);
Per evitare di esporre o divulgare dati sensibili in una tabella o di eseguire
comandi come DROP TABLE
per eliminare dati in una tabella, le istruzioni procedurali dinamiche di BigQuery
supportano più misure di sicurezza per
ridurre l'esposizione ad attacchi di SQL injection, tra cui:
- Un'istruzione
EXECUTE IMMEDIATE
non consente alla query, espansa con parametri e variabili di query, di incorporare più istruzioni SQL. - L'esecuzione dinamica dei seguenti comandi è limitata:
BEGIN
/END
,CALL
,CASE
,IF
,LOOP
,WHILE
eEXECUTE IMMEDIATE
.
Limitazioni dei campi di configurazione
I seguenti campi di query di configurazione del job non possono essere impostati per una query con più istruzioni:
clustering
create_disposition
destination_table
destination_encryption_configuration
range_partitioning
schema_update_options
time_partitioning
user_defined_function_resources
write_disposition
Prezzi
I prezzi per le query con più istruzioni includono gli addebiti per le query (quando utilizzi il modello di fatturazione on demand) e l'archiviazione per le tabelle temporanee. Quando utilizzi le prenotazioni, l'utilizzo delle query è coperto dagli addebiti per la prenotazione.
Calcolo delle dimensioni delle query on demand
Se utilizzi la fatturazione on demand, BigQuery addebita i costi per le query multi-istruzione in base al numero di byte elaborati durante l'esecuzione delle query multi-istruzione.
Per ottenere una stima del numero di byte che una query multi-istruzione potrebbe elaborare, puoi eseguire un test dry run.
Per queste query multi-istruzione si applicano i seguenti prezzi:
DECLARE
: la somma dei byte analizzati per le tabelle cui viene fatto riferimento nell'espressioneDEFAULT
. Le istruzioniDECLARE
senza riferimenti a tabelle non sono addebitate.SET
: la somma dei byte analizzati per le tabelle cui viene fatto riferimento nell'espressione. Le istruzioniSET
senza riferimenti a tabelle non sono addebitate.IF
: la somma dei byte analizzati per le tabelle cui viene fatto riferimento nell'espressione della condizione. Le espressioni della condizioneIF
senza riferimenti a tabelle non sono addebitate. Eventuali istruzioni non eseguite all'interno del bloccoIF
non sono addebitate.WHILE
: la somma dei byte analizzati per le tabelle cui viene fatto riferimento nell'espressione della condizione. Le istruzioniWHILE
senza riferimenti a tabelle nell'espressione della condizione non sono addebitate. Eventuali istruzioni non eseguite all'interno del bloccoWHILE
non sono addebitate.CONTINUE
oITERATE
: nessun costo associato.BREAK
oLEAVE
: nessun costo associato.BEGIN
oEND
: nessun costo associato.
Se una query con più istruzioni non riesce, il costo di eventuali istruzioni fino al momento dell'errore sarà comunque applicato. L'istruzione con esito negativo non sarà addebitata.
Ad esempio, il seguente codice campione contiene commenti che precedono ogni istruzione e che spiegano gli eventuali costi applicati da ciascuna istruzione:
-- 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;
Per ulteriori informazioni, vedi Calcolo delle dimensioni delle query.
Prezzi di archiviazione
Ti vengono addebitati costi per le tabelle temporanee create da query con più istruzioni. Puoi utilizzare le visualizzazioni
TABLE_STORAGE
o
TABLE_STORAGE_USAGE_TIMELINE
per visualizzare lo spazio di archiviazione utilizzato da queste tabelle temporanee. Le tabelle temporanee si trovano in set di dati _script%
nascosti con nomi generati in modo casuale.
Quote
Per informazioni sulle quote delle query multi-istruzione, consulta Quote e limiti.
Visualizzare il numero di query multi-istruzione
Puoi visualizzare il numero di query multi-statement attive utilizzando la
visualizzazione INFORMATION_SCHEMA.JOBS_BY_PROJECT
.
Il seguente esempio utilizza la vista INFORMATION_SCHEMA.JOBS_BY_PROJECT
per
mostrare il numero di query con più istruzioni del giorno precedente:
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'
Per saperne di più sull'esecuzione di query su INFORMATION_SCHEMA.JOBS
per
query con più istruzioni, consulta Job di query con più istruzioni.