STRUCT(2 AS line, 3 AS column, NULL AS filename, "<project>.schema1.proc1:2:3" AS location),
STRUCT(2 AS line, 3 AS column, NULL AS filename, "<project>.schema1.proc2:2:3" AS location),
STRUCT(10 AS line, 3 AS column, NULL AS filename, NULL AS location),
]
@@error.statement_text
"SELECT 1/0"
@@error.formatted_stack_trace
"At <project>.schema1.proc1[2:3]\nAt <project>.schema1.proc2[2:3]\nAt [10:3]"
CASE
Syntax
CASEWHENboolean_expressionTHENsql_statement_list[...][ELSEsql_statement_list]ENDCASE;
Description
Executes the THEN sql_statement_list
where the boolean expression is true, or the optional ELSE sql_statement_list
if no conditions match.
CASE
can have a maximum of 50 nesting levels.
CASE
is restricted from being executed dynamically as a nested element. This means CASE
can't be nested in an EXECUTE IMMEDIATE
statement.
Examples
In this example, a search if conducted for the target_product_ID
in the products_a
table. If the ID isn't found there, a search is conducted for the ID in the products_b
table. If the ID isn't found there, the statement in the ELSE
block is executed.
DECLAREtarget_product_idINT64DEFAULT103;CASEWHENEXISTS(SELECT1FROMschema.products_aWHEREproduct_id=target_product_id)THENSELECT'found product in products_a table';WHENEXISTS(SELECT1FROMschema.products_bWHEREproduct_id=target_product_id)THENSELECT'found product in products_b table';ELSESELECT'did not find product';ENDCASE;
CASE search_expression
Syntax
CASEsearch_expressionWHENexpressionTHENsql_statement_list[...][ELSEsql_statement_list]ENDCASE;
Description
Executes the first sql_statement_list
where the search expression is matches a WHEN
expression. The search_expression
is evaluated once and then tested against each WHEN
expression for equality until a match is found. If no match is found, then the optional ELSE
sql_statement_list
is executed.
CASE
can have a maximum of 50 nesting levels.
CASE
is restricted from being executed dynamically as a nested element. This means CASE
can't be nested in an EXECUTE IMMEDIATE
statement.
Examples
The following example uses the product ID as the search expression. If the ID is 1
, 'Product one'
is returned. If the ID is 2
, 'Product two'
is returned. If the ID is anything else, Invalid product
is returned.
DECLAREproduct_idINT64DEFAULT1;CASEproduct_idWHEN1THENSELECTCONCAT('Product one');WHEN2THENSELECTCONCAT('Product two');ELSESELECTCONCAT('Invalid product');ENDCASE;
IF
Syntax
IFconditionTHEN[sql_statement_list][ELSEIFconditionTHENsql_statement_list][...][ELSEsql_statement_list]ENDIF;
Description
Executes the first sql_statement_list
where the condition is true, or the optional ELSE
sql_statement_list
if no conditions match.
There is a maximum nesting level of 50 for blocks and conditional statements such as BEGIN
/END
, IF
/ELSE
/END IF
, and WHILE
/END WHILE
.
IF
is restricted from being executed dynamically as a nested element. This means IF
can't be nested in an EXECUTE IMMEDIATE
statement.
Examples
The following example declares a INT64 variable target_product_id
with a default value of 103; then, it checks whether the table schema.products
contains a row with the product_id
column matches the value of target_product_id
; if so, it outputs a string stating that the product has been found, along with the value of default_product_id
; if not, it outputs a string stating that the product hasn't been found, also with the value of default_product_id
.
DECLAREtarget_product_idINT64DEFAULT103;IFEXISTS(SELECT1FROMschema.productsWHEREproduct_id=target_product_id)THENSELECTCONCAT('found product ',CAST(target_product_idASSTRING));ELSEIFEXISTS(SELECT1FROMschema.more_productsWHEREproduct_id=target_product_id)THENSELECTCONCAT('found product from more_products table',CAST(target_product_idASSTRING));ELSESELECTCONCAT('did not find product ',CAST(target_product_idASSTRING));ENDIF;
Syntax
label_name:BEGINblock_statement_listEND[label_name];
label_name:LOOPloop_statement_listENDLOOP[label_name];
label_name:WHILEconditionDOloop_statement_listENDWHILE[label_name];
label_name:FORvariableINqueryDOloop_statement_listENDFOR[label_name];
label_name:REPEATloop_statement_listUNTILboolean_conditionENDREPEAT[label_name];
block_statement_list:{statement|break_statement_with_label}[,...]loop_statement_list:{statement|break_continue_statement_with_label}[,...]break_statement_with_label:{BREAK|LEAVE}label_name;break_continue_statement_with_label:{BREAK|LEAVE|CONTINUE|ITERATE}label_name;
Description
A BREAK or CONTINUE statement with a label provides an unconditional jump to the end of the block or loop associated with that label. To use a label with a block or loop, the label must appear at the beginning of the block or loop, and optionally at the end.
Multipart path names can be used, but only as quoted identifiers.
`foo.bar`: BEGIN ... END -- Works foo.bar: BEGIN ... END -- Doesn't work
Label names are case-insensitive.
Each stored procedure has an independent store of label names. For example, a procedure may redefine a label already used in a calling procedure.
A loop or block may not repeat a label name used in an enclosing loop or block.
Repeated label names are allowed in non-overlapping parts in procedural statements.
A label and variable with the same name is allowed.
When the BREAK
, LEAVE
, CONTINUE
, or ITERATE
statement specifies a label, it exits or continues the loop matching the label name, rather than always picking the innermost loop.
Examples
You can only reference a block or loop while inside of it.
label_1:BEGINSELECT1;BREAKlabel_1;SELECT2;-- UnreachedEND;
label_1:LOOPBREAKlabel_1;ENDLOOPlabel_1;WHILEx < 1DOCONTINUElabel_1;-- ErrorENDWHILE;
Repeated label names are allowed in non-overlapping parts of the multi-statement query. This works:
label_1:BEGINBREAKlabel_1;END;label_2:BEGINBREAKlabel_2;END;label_1:BEGINBREAKlabel_1;END;
A loop or block may not repeat a label name used in an enclosing loop or block. This throws an error:
label_1:BEGINlabel_1:BEGIN-- ErrorBREAKlabel_1;END;END;
A label and variable can have same name. This works:
label_1:BEGINDECLARElabel_1INT64;BREAKlabel_1;END;
The END
keyword terminating a block or loop may specify a label name, but this is optional. These both work:
label_1:BEGINBREAKlabel_1;ENDlabel_1;
label_1:BEGINBREAKlabel_1;END;
You can't have a label at the end of a block or loop if there isn't a label at the beginning of the block or loop. This throws an error:
BEGINBREAKlabel_1;ENDlabel_1;
In this example, the BREAK
and CONTINUE
statements target the outer label_1: LOOP
, rather than the inner WHILE x < 1 DO
loop:
label_1:LOOPWHILEx < 1DOIFy < 1THENCONTINUElabel_1;ELSEBREAKlabel_1;ENDWHILE;ENDLOOPlabel_1
A BREAK
, LEAVE
, or CONTINUE
, or ITERATE
statement that specifies a label that doesn't exist throws an error:
WHILEx < 1DOBREAKlabel_1;-- ErrorENDWHILE;
Exiting a block from within the exception handler section is allowed:
label_1:BEGINSELECT1;EXCEPTIONWHENERRORTHENBREAKlabel_1;SELECT2;-- UnreachedEND;
CONTINUE
can't be used with a block label. This throws an error:
label_1:BEGINSELECT1;CONTINUElabel_1;-- ErrorSELECT2;END;
LOOP
Syntax
LOOPsql_statement_listENDLOOP;
Description
Executes sql_statement_list
until a BREAK
or LEAVE
statement exits the loop. sql_statement_list
is a list of zero or more SQL statements ending with semicolons.
LOOP
is restricted from being executed dynamically as a nested element. This means LOOP
can't be nested in an EXECUTE IMMEDIATE
statement.
You can use a label with this statement. To learn more, see Labels.
Examples
The following example declares a variable x
with the default value 0; then, it uses the LOOP
statement to create a loop that executes until the variable x
is greater than or equal to 10; after the loop exits, the example outputs the value of x
.
DECLARExINT64DEFAULT0;LOOPSETx=x+1;IFx>=10THENLEAVE;ENDIF;ENDLOOP;SELECTx;
This example outputs the following:
/*----* | x | +----+ | 10 | *----*/
REPEAT
Syntax
REPEATsql_statement_listUNTILboolean_conditionENDREPEAT;
Description
Repeatedly executes a list of zero or more SQL statements until the boolean condition at the end of the list is TRUE
. The boolean condition must be an expression. You can exit this loop early with the BREAK
or LEAVE
statement.
REPEAT
is restricted from being executed dynamically as a nested element. This means REPEAT
can't be nested in an EXECUTE IMMEDIATE
statement.
You can use a label with this statement. To learn more, see Labels.
Examples
The following example declares a variable x
with the default value 0
; then, it uses the REPEAT
statement to create a loop that executes until the variable x
is greater than or equal to 3
.
DECLARExINT64DEFAULT0;REPEATSETx=x+1;SELECTx;UNTILx>=3ENDREPEAT;
This example outputs the following:
/*---* | x | +---+ | 1 | *---*//*---* | x | +---+ | 2 | *---*//*---* | x | +---+ | 3 | *---*/
WHILE
Syntax
WHILEboolean_expressionDOsql_statement_listENDWHILE;
There is a maximum nesting level of 50 for blocks and conditional statements such as BEGIN
/END
, IF
/ELSE
/END IF
, and WHILE
/END WHILE
.
Description
While boolean_expression
is true, executes sql_statement_list
. boolean_expression
is evaluated for each iteration of the loop.
WHILE
is restricted from being executed dynamically as a nested element. This means WHILE
can't be nested in an EXECUTE IMMEDIATE
statement.
You can use a label with this statement. To learn more, see Labels.
BREAK
Syntax
BREAK;
Description
Exit the current loop.
It's an error to use BREAK
outside of a loop.
You can use a label with this statement. To learn more, see Labels.
Examples
The following example declares two variables, heads
and heads_count
; next, it initiates a loop, which assigns a random boolean value to heads
, then checks to see whether heads
is true; if so, it outputs "Heads!" and increments heads_count
; if not, it outputs "Tails!" and exits the loop; finally, it outputs a string stating how many times the "coin flip" resulted in "heads."
DECLAREheadsBOOL;DECLAREheads_countINT64DEFAULT0;LOOPSETheads=RAND() < 0.5;IFheadsTHENSELECT'Heads!';SETheads_count=heads_count+1;ELSESELECT'Tails!';BREAK;ENDIF;ENDLOOP;SELECTCONCAT(CAST(heads_countASSTRING),' heads in a row');
LEAVE
Synonym for BREAK
.
CONTINUE
Syntax
CONTINUE;
Description
Skip any following statements in the current loop and return to the start of the loop.
It's an error to use CONTINUE
outside of a loop.
You can use a label with this statement. To learn more, see Labels.
Examples
The following example declares two variables, heads
and heads_count
; next, it initiates a loop, which assigns a random boolean value to heads
, then checks to see whether heads
is true; if so, it outputs "Heads!", increments heads_count
, and restarts the loop, skipping any remaining statements; if not, it outputs "Tails!" and exits the loop; finally, it outputs a string stating how many times the "coin flip" resulted in "heads."
DECLAREheadsBOOL;DECLAREheads_countINT64DEFAULT0;LOOPSETheads=RAND() < 0.5;IFheadsTHENSELECT'Heads!';SETheads_count=heads_count+1;CONTINUE;ENDIF;SELECT'Tails!';BREAK;ENDLOOP;SELECTCONCAT(CAST(heads_countASSTRING),' heads in a row');
ITERATE
Synonym for CONTINUE
.
FOR...IN
Syntax
FORloop_variable_nameIN(table_expression)DOsql_expression_listENDFOR;
Description
Loops over every row in table_expression
and assigns the row to loop_variable_name
. Inside each loop, the SQL statements in sql_expression_list
are executed using the current value of loop_variable_name
.
The value of table_expression
is evaluated once at the start of the loop. On each iteration, the value of loop_variable_name
is a STRUCT
that contains the top-level columns of the table expression as fields. The order in which values are assigned to loop_variable_name
isn't defined, unless the table expression has a top-level ORDER BY
clause or UNNEST
array operator.
The scope of loop_variable_name
is the body of the loop. The name of loop_variable_name
can't conflict with other variables within the same scope.
You can use a label with this statement. To learn more, see Labels.
Example
FORrecordIN(SELECTword,word_countFROMbigquery-public-data.samples.shakespeareLIMIT5)DOSELECTrecord.word,record.word_count;ENDFOR;
BEGIN TRANSACTION
Syntax
BEGIN[TRANSACTION];
Description
Begins a transaction.
The transaction ends when a COMMIT TRANSACTION
or ROLLBACK TRANSACTION
statement is reached. If execution ends before reaching either of these statements, an automatic rollback occurs.
For more information about transactions in BigQuery, see Multi-statement transactions.
Example
The following example performs a transaction that selects rows from an existing table into a temporary table, deletes those rows from the original table, and merges the temporary table into another table.
BEGINTRANSACTION;-- Create a temporary table of new arrivals from warehouse #1CREATETEMPTABLEtmpASSELECT*FROMmyschema.NewArrivalsWHEREwarehouse='warehouse #1';-- Delete the matching records from the original table.DELETEmyschema.NewArrivalsWHEREwarehouse='warehouse #1';-- Merge the matching records into the Inventory table.MERGEmyschema.InventoryASIUSINGtmpASTONI.product=T.productWHENNOTMATCHEDTHENINSERT(product,quantity,supply_constrained)VALUES(product,quantity,false)WHENMATCHEDTHENUPDATESETquantity=I.quantity+T.quantity;DROPTABLEtmp;COMMITTRANSACTION;
COMMIT TRANSACTION
Syntax
COMMIT[TRANSACTION];
Description
Commits an open transaction. If no open transaction is in progress, then the statement fails.
For more information about transactions in BigQuery, see Multi-statement transactions.
Example
BEGINTRANSACTION;-- SQL statements for the transaction go here.COMMITTRANSACTION;
ROLLBACK TRANSACTION
Syntax
ROLLBACK[TRANSACTION];
Description
Rolls back an open transaction. If there is no open transaction in progress, then the statement fails.
For more information about transactions in BigQuery, see Multi-statement transactions.
Example
The following example rolls back a transaction if an error occurs during the transaction. To illustrate the logic, the example triggers a divide-by-zero error after inserting a row into a table. After these statements run, the table is unaffected.
BEGINBEGINTRANSACTION;INSERTINTOmyschema.NewArrivalsVALUES('top load washer',100,'warehouse #1');-- Trigger an error.SELECT1/0;COMMITTRANSACTION;EXCEPTIONWHENERRORTHEN-- Roll back the transaction inside the exception handler.SELECT@@error.message;ROLLBACKTRANSACTION;END;
RAISE
Syntax
RAISE[USINGMESSAGE=message];
Description
Raises an error, optionally using the specified error message when USING MESSAGE = message
is supplied.
USING MESSAGE
isn't suppliedThe RAISE
statement must only be used within an EXCEPTION
clause. The RAISE
statement will re-raise the exception that was caught, and preserve the original stack trace.
USING MESSAGE
is suppliedIf the RAISE
statement is contained within the BEGIN
section of a BEGIN...EXCEPTION
block:
The value of @@error.message
will exactly match the message
string supplied (which may be NULL
if message
is NULL
).
The stack trace will be set to the RAISE
statement.
If the RAISE
statement isn't contained within the BEGIN
section of a BEGIN...EXCEPTION
block, the RAISE
statement stops execution of the multi-statement query with the error message supplied.
RETURN
RETURN
stops execution of the multi-statements query.
CALL
Syntax
CALLprocedure_name(procedure_argument[,…])
Description
Calls a procedure with an argument list. procedure_argument
may be a variable or an expression.
For OUT
or INOUT
arguments, a variable passed as an argument must have the proper GoogleSQL type. The same variable may not appear multiple times as an OUT
or INOUT
argument in the procedure's argument list.
The maximum depth of procedure calls is 50 frames.
CALL
is restricted from being executed dynamically as a nested element. This means CALL
can't be nested in an EXECUTE IMMEDIATE
statement.
Examples
The following example declares a variable retCode
. Then, it calls the procedure updateSomeTables
in the schema mySchema
, passing the arguments 'someAccountId'
and retCode
. Finally, it returns the value of retCode
.
DECLAREretCodeINT64;-- Procedure signature: (IN account_id STRING, OUT retCode INT64)CALLmySchema.UpdateSomeTables('someAccountId',retCode);SELECTretCode;
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-04-24 UTC.