El lenguaje de procedimiento de SQL estándar de Google te permite ejecutar varias instrucciones en una consulta como una consulta de varias instrucciones. Puedes usar una consulta de varias declaraciones para lo siguiente:
- Ejecuta varias consultas en una secuencia, con estado compartido.
- Automatiza las tareas de administración, como crear o descartar tablas
- Implementa una lógica compleja con construcciones de programación como
IF
yWHILE
.
Esta referencia contiene las instrucciones que forman parte del lenguaje de procedimiento de SQL estándar de Google. Si deseas obtener más información sobre cómo puedes usar este lenguaje de procedimiento para escribir consultas de varias declaraciones, consulta Trabaja con consultas de varias declaraciones. Para obtener información sobre cómo convertir las consultas de varias declaraciones en procedimientos almacenados, consulta Trabaja con procedimientos almacenados.
DECLARE
DECLARE variable_name[, ...] [variable_type] [DEFAULT expression];
variable_name
debe ser un identificador válido, y variable_type
es cualquier tipo de SQL estándar de Google.
Descripción
Declara una variable del tipo especificado. Si se especifica la cláusula DEFAULT
, la variable se inicializa con el valor de la expresión; si no hay una cláusula DEFAULT
, la variable se inicializa con el valor NULL
.
Si se omite [variable_type]
, se debe especificar una cláusula DEFAULT
. El tipo de la variable se inferirá según el tipo de la expresión en la cláusula DEFAULT
.
Las instrucciones de variables deben aparecer antes de otras instrucciones de procedimiento o al comienzo de un bloque de BEGIN
. Los nombres de las variables distinguen mayúsculas de minúsculas.
Pueden aparecer varios nombres de variables en una sola declaración DECLARE
, pero solo una variable_type
y expression
.
Es un error declarar una variable con el mismo nombre que una variable declarada anteriormente en el bloque actual o en un bloque contenedor.
Si la cláusula DEFAULT
está presente, el valor de la expresión debe ser coercible para el tipo especificado. La expresión puede hacer referencia a otras variables declaradas previamente dentro del mismo bloque o un bloque contenedor.
Ejemplos
En el siguiente ejemplo, se inicializa la variable x
como un INT64 con el valor NULL
.
DECLARE x INT64;
En el siguiente ejemplo, se inicializa la variable d
como DATE con el valor de la fecha actual.
DECLARE d DATE DEFAULT CURRENT_DATE();
En el siguiente ejemplo, se inicializan las variables x
, y
y z
como INT64
con el valor 0.
DECLARE x, y, z INT64 DEFAULT 0;
En el siguiente ejemplo, se declara una variable llamada item
que corresponde a un elemento arbitrario en la tabla dataset1.products
. Se infiere el tipo de item
del esquema de la tabla.
DECLARE item DEFAULT (SELECT item FROM dataset1.products LIMIT 1);
SET
Sintaxis
SET variable_name = expression;
SET (variable_name[, ...]) = (expression[, ...]);
Descripción
Establece una variable para tener el valor de la expresión proporcionada, o establece muchas variables al mismo tiempo en función del resultado de varias expresiones.
La instrucción SET
puede aparecer en cualquier parte dentro de una consulta de varias instrucciones.
Ejemplos
En el siguiente ejemplo, se establece que la variable x
tenga el valor 5.
SET x = 5;
En el siguiente ejemplo, se establece que la variable a
tenga el valor 4, que la variable b
tenga el valor ‘foo’ y que la variable c
tenga el valor false
.
SET (a, b, c) = (1 + 3, 'foo', false);
En el siguiente ejemplo, se asigna el resultado de una consulta a muchas variables.
Primero, declara dos variables, target_word
y corpus_count
; a continuación, asigna los resultados de una consulta SELECT AS STRUCT
a las dos variables. El resultado de la consulta es una sola fila que contiene un STRUCT
con dos campos; el primer elemento se asigna a la primera variable y el segundo elemento se asigna a la segunda variable.
DECLARE target_word STRING DEFAULT 'methinks'; DECLARE corpus_count, word_count INT64; SET (corpus_count, word_count) = ( SELECT AS STRUCT COUNT(DISTINCT corpus), SUM(word_count) FROM `bigquery-public-data`.samples.shakespeare WHERE LOWER(word) = target_word ); SELECT FORMAT('Found %d occurrences of "%s" across %d Shakespeare works', word_count, target_word, corpus_count) AS result;
Con esta lista de declaraciones se genera la siguiente string:
Found 151 occurrences of "methinks" across 38 Shakespeare works
EXECUTE IMMEDIATE
Sintaxis
EXECUTE IMMEDIATE sql_expression [ INTO variable[, ...] ] [ USING identifier[, ...] ];
sql_expression:
{ "query_statement" | expression("query_statement") }
identifier:
{ variable | value } [ AS alias ]
Descripción
Ejecuta una declaración de SQL dinámica sobre la marcha.
sql_expression
: Representa una declaración de consulta, una expresión que puedes usar en una declaración de consulta, una única declaración DDL o una única declaración DML. No puede ser una declaración de control comoIF
.expression
: Puede ser una función, una expresión condicional o una subconsulta de expresión.query_statement
: Representa una declaración de SQL independiente válida para ejecutar. Si esto muestra un valor, la cláusulaINTO
debe contener valores del mismo tipo. Puedes acceder a las variables del sistema y los valores presentes en la cláusulaUSING
. Todas las demás variables locales y parámetros de consulta no están expuestos a la declaración de consulta.- Cláusula
INTO
: Después de ejecutar la expresión de SQL, puedes almacenar los resultados en una o más variables mediante la cláusulaINTO
. - Cláusula
USING
: Antes de ejecutar la expresión de SQL, puedes pasar uno o más identificadores de la cláusulaUSING
a la expresión de SQL. Estos identificadores funcionan de manera similar a los parámetros de consulta y exponen valores a la declaración de consulta. Un identificador puede ser una variable o un valor.
Puedes incluir estos marcadores de posición en query_statement
para los identificadores a los que se hace referencia en la cláusula USING
:
?
: El valor de este marcador de posición se vincula por índice a un identificador en la cláusulaUSING
.-- y = 1 * (3 + 2) = 5 EXECUTE IMMEDIATE "SELECT ? * (? + 2)" INTO y USING 1, 3;
@identifier
: El valor de este marcador de posición se vincula por nombre a un identificador en la cláusulaUSING
. Esta sintaxis es idéntica a la del parámetro de consulta.-- y = 1 * (3 + 2) = 5 EXECUTE IMMEDIATE "SELECT @a * (@b + 2)" INTO y USING 1 as a, 3 as b;
Estas son algunas notas adicionales sobre el comportamiento de la declaración EXECUTE IMMEDIATE
:
EXECUTE IMMEDIATE
no puede ejecutarse de forma dinámica como un elemento anidado. Esto significa queEXECUTE IMMEDIATE
no se puede anidar en otra declaraciónEXECUTE IMMEDIATE
.- Si una declaración
EXECUTE IMMEDIATE
muestra resultados, esos resultados se convierten en el resultado de toda la declaración y se actualizan las variables de sistema adecuadas. - La misma variable puede aparecer en las cláusulas
INTO
yUSING
. query_statement
puede contener una sola declaración analizada que contenga otras declaraciones (por ejemplo, BEGIN…END).- Si
query_statement
no muestra ninguna fila, incluso las tablas de valores sin filas, todas las variables en la cláusulaINTO
se establecen como NULL. - Si
query_statement
muestra una fila, incluso las tablas de valores sin filas, los valores se asignan por posición, no por nombre de variable. - Si hay una cláusula
INTO
, se genera un error si intentas mostrar más de una fila dequery_statement
.
Ejemplos
En este ejemplo, creamos una tabla de libros y la propagamos con datos. Ten en cuenta las diferentes formas en las que puedes hacer referencia a las variables, guardar valores en variables y usar expresiones.
-- create some variables
DECLARE book_name STRING DEFAULT 'Ulysses';
DECLARE book_year INT64 DEFAULT 1922;
DECLARE first_date INT64;
-- Create a temporary table called Books.
EXECUTE IMMEDIATE
"CREATE TEMP TABLE Books (title STRING, publish_date INT64)";
-- Add a row for Hamlet (less secure)
EXECUTE IMMEDIATE
"INSERT INTO Books (title, publish_date) VALUES('Hamlet', 1599)";
-- add a row for Ulysses, using the variables declared and the ? placeholder
EXECUTE IMMEDIATE
"INSERT INTO Books (title, publish_date) VALUES(?, ?)"
USING book_name, book_year;
-- add a row for Emma, using the identifier placeholder
EXECUTE IMMEDIATE
"INSERT INTO Books (title, publish_date) VALUES(@name, @year)"
USING 1815 as year, "Emma" as name;
-- add a row for Middlemarch, using an expression
EXECUTE IMMEDIATE
CONCAT(
"INSERT INTO Books (title, publish_date)", "VALUES('Middlemarch', 1871)"
);
-- save the publish date of the first book, Hamlet, to a variable called
-- first_date
EXECUTE IMMEDIATE "SELECT publish_date FROM Books LIMIT 1" INTO first_date;
+------------------+------------------+
| title | publish_date |
+------------------+------------------+
| Hamlet | 1599 |
| Ulysses | 1922 |
| Emma | 1815 |
| Middlemarch | 1871 |
+------------------+------------------+
BEGIN…END
Sintaxis
BEGIN sql_statement_list END;
Descripción
BEGIN
inicia un bloque de declaraciones donde las variables declaradas existen solo hasta el END
correspondiente. sql_statement_list
es una lista de cero o más instrucciones de SQL que terminan en punto y coma.
Las declaraciones de variables deben aparecer al comienzo del bloque, antes de otros tipos de declaraciones. Las variables declaradas dentro de un bloque solo pueden referenciarse dentro de ese bloque y en cualquier bloque anidado. Es un error declarar una variable con el mismo nombre que una variable declarada en el mismo bloque o en un bloque externo.
Hay un nivel máximo de anidación de 50 para bloques y declaraciones condicionales como BEGIN
/END
, IF
/ELSE
/END IF
y WHILE
/END WHILE
.
BEGIN
/END
no se puede ejecutar de forma dinámica como un elemento anidado.
Puedes usar una etiqueta con esta declaración. Para obtener más información, consulta Etiquetas.
Ejemplos
En el siguiente ejemplo, se declara una variable x
con el valor predeterminado 10. Luego, se inicia un bloque, en el que a una variable y
se le asigna el valor de x
, que es 10, y muestra este valor. Luego, la declaración END
finaliza el bloque, y finaliza el alcance de la variable y
. Por último, muestra el valor de x
.
DECLARE x INT64 DEFAULT 10; BEGIN DECLARE y INT64; SET y = x; SELECT y; END; SELECT x;
BEGIN…EXCEPTION…END
Sintaxis
BEGIN sql_statement_list EXCEPTION WHEN ERROR THEN sql_statement_list END;
Descripción
BEGIN...EXCEPTION
ejecuta un bloque de declaraciones. Si alguna de las instrucciones experimenta un error, se omite el resto del bloque y se ejecutan las instrucciones en la cláusula EXCEPTION
.
En la cláusula EXCEPTION
, puedes acceder a los detalles del error mediante las siguientes variables de sistema EXCEPTION
:
Nombre | Tipo | Descripción |
---|---|---|
@@error.formatted_stack_trace |
STRING |
El contenido de @@error.stack_trace se expresa como una string legible para el ser humano. Este valor está destinado a fines de visualización y está sujeto a cambios sin previo aviso. En su lugar, el acceso programático al seguimiento de pila de un error debería usar @@error.stack_trace . |
@@error.message |
STRING |
Especifica un mensaje de error legible para el ser humano. |
@@error.stack_trace |
Consulta 1. | Cada elemento del arreglo corresponde a una declaración o llamada a procedimiento que se ejecuta en el momento del error, y el primer marco de pila que está en ejecución aparece primero. El significado de cada campo se define de la siguiente manera:
|
@@error.statement_text |
STRING |
Especifica el texto de la declaración que causó el error. |
1 El tipo para @@error.stack_trace
es ARRAY<STRUCT<line INT64, column INT64, filename STRING, location STRING>>
.
Como BigQuery se reserva el derecho de revisar los mensajes de error en cualquier momento, los consumidores de @@error.message
no deben confiar en que los mensajes de error permanezcan iguales o sigan un patrón en particular. No obtengas información sobre la ubicación del error mediante la extracción de texto del mensaje de error; en su lugar, usa @@error.stack_trace
y @@error.statement_text
.
Para controlar las excepciones que arroja (sin control) un controlador de excepciones, debes unir el bloque a otro externo con un controlador independiente.
A continuación, se muestra cómo usar un bloque externo con un controlador de excepciones independiente:
BEGIN BEGIN ... EXCEPTION WHEN ERROR THEN SELECT 1/0; END; EXCEPTION WHEN ERROR THEN -- The exception thrown from the inner exception handler lands here. END;
Los bloques BEGIN...EXCEPTION
también admiten instrucciones DECLARE
, como cualquier otro bloque BEGIN
. Las variables declaradas en un bloque BEGIN
son válidas solo en la sección BEGIN
y no se pueden usar en el controlador de excepciones del bloque.
Puedes usar una etiqueta con esta declaración. Para obtener más información, consulta Etiquetas.
Ejemplos
CREATE OR REPLACE PROCEDURE dataset1.proc1() BEGIN SELECT 1/0; END; CREATE OR REPLACE PROCEDURE dataset1.proc2() BEGIN CALL dataset1.proc1(); END; BEGIN CALL dataset1.proc2(); EXCEPTION WHEN ERROR THEN SELECT @@error.message, @@error.stack_trace, @@error.statement_text, @@error.formatted_stack_trace; END;
En este ejemplo, cuando ocurra el error de división por cero, en lugar de finalizar toda la secuencia de comandos de varias instrucciones, BigQuery finalizará dataset1.proc1()
y dataset1.proc2()
, y ejecutará la instrucción SELECT en el controlador de excepciones. Cuando se ejecute el controlador de excepciones, las variables tendrán los siguientes valores:
Variable | Valor |
---|---|
@@error.message |
"Query error: division by zero: 1 / 0 at <project>.dataset1.proc1:2:3]" |
@@error.stack_trace |
[ STRUCT(2 AS line, 3 AS column, NULL AS filename, "<project>.dataset1.proc1:2:3" AS location), STRUCT(2 AS line, 3 AS column, NULL AS filename, "<project>.dataset1.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>.dataset1.proc1[2:3]\nAt <project>.dataset1.proc2[2:3]\nAt [10:3]" |
CASE
Sintaxis
CASE WHEN boolean_expression THEN sql_statement_list [...] [ELSE sql_statement_list] END CASE;
Descripción
Ejecuta THEN sql_statement_list
en la que la expresión booleana es verdadera, o ELSE sql_statement_list
opcional si no hay condiciones coincidentes.
CASE
puede tener un máximo de 50 niveles de anidación.
CASE
no puede ejecutarse de forma dinámica como un elemento anidado. Esto
significa que CASE
no se puede anidar en una declaración EXECUTE IMMEDIATE
.
Ejemplos
En este ejemplo, se realiza una búsqueda de target_product_ID
en la tabla products_a
. Si el ID no se encuentra allí, se realiza una búsqueda del ID en la tabla products_b
. Si el ID no se encuentra allí, se ejecuta la instrucción en el bloque ELSE
.
DECLARE target_product_id INT64 DEFAULT 103; CASE WHEN EXISTS(SELECT 1 FROM dataset.products_a WHERE product_id = target_product_id) THEN SELECT 'found product in products_a table'; WHEN EXISTS(SELECT 1 FROM dataset.products_b WHERE product_id = target_product_id) THEN SELECT 'found product in products_b table'; ELSE SELECT 'did not find product'; END CASE;
CASE search_expression
Sintaxis
CASE search_expression WHEN expression THEN sql_statement_list [...] [ELSE sql_statement_list] END CASE;
Descripción
Ejecuta la primera sql_statement_list
en la que la expresión de búsqueda coincide con una expresión WHEN
. search_expression
se evalúa una vez y, luego, se prueba con cada expresión WHEN
para determinar la igualdad hasta que se encuentre una coincidencia.
Si no se encuentran coincidencias, se ejecuta el sql_statement_list
de ELSE
opcional.
CASE
puede tener un máximo de 50 niveles de anidación.
CASE
no puede ejecutarse de forma dinámica como un elemento anidado. Esto
significa que CASE
no se puede anidar en una declaración EXECUTE IMMEDIATE
.
Ejemplos
En el siguiente ejemplo, se usa el ID del producto como expresión de búsqueda. Si el ID es 1
, se muestra 'Product one'
. Si el ID es 2
, se muestra 'Product two'
. Si el ID es distinto, se muestra Invalid product
.
DECLARE product_id INT64 DEFAULT 1; CASE product_id WHEN 1 THEN SELECT CONCAT('Product one'); WHEN 2 THEN SELECT CONCAT('Product two'); ELSE SELECT CONCAT('Invalid product'); END CASE;
IF
Sintaxis
IF condition THEN [sql_statement_list]
[ELSEIF condition THEN sql_statement_list]
[...]
[ELSE sql_statement_list]
END IF;
Descripción
Ejecuta la primera sql_statement_list
en la que la condición es verdadera o la ELSE
sql_statement_list
opcional si las condiciones no coinciden.
Hay un nivel máximo de anidación de 50 para bloques y declaraciones condicionales como BEGIN
/END
, IF
/ELSE
/END IF
y WHILE
/END WHILE
.
IF
no puede ejecutarse de forma dinámica como un elemento anidado. Esto
significa que IF
no se puede anidar en una declaración EXECUTE IMMEDIATE
.
Ejemplos
En el siguiente ejemplo, se declara una variable INT64 target_product_id
con un valor predeterminado de 103. Luego, se verifica si la tabla dataset.products
contiene una fila con la columna product_id
que coincide con el valor de target_product_id
. Si es así, se da como resultado una string que indica que se ha encontrado el producto, junto con el valor de default_product_id
. En caso contrario, se da como resultado una string que indica que no se ha encontrado el producto, también con el valor de default_product_id
.
DECLARE target_product_id INT64 DEFAULT 103;
IF EXISTS(SELECT 1 FROM dataset.products
WHERE product_id = target_product_id) THEN
SELECT CONCAT('found product ', CAST(target_product_id AS STRING));
ELSEIF EXISTS(SELECT 1 FROM dataset.more_products
WHERE product_id = target_product_id) THEN
SELECT CONCAT('found product from more_products table',
CAST(target_product_id AS STRING));
ELSE
SELECT CONCAT('did not find product ', CAST(target_product_id AS STRING));
END IF;
Etiquetas
Sintaxis
label_name: BEGIN block_statement_list END [label_name];
label_name: LOOP loop_statement_list END LOOP [label_name];
label_name: WHILE condition DO
loop_statement_list
END WHILE [label_name];
label_name: FOR variable IN query DO
loop_statement_list
END FOR [label_name];
label_name: REPEAT loop_statement_list UNTIL boolean_condition END REPEAT [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;
Descripción
Una declaración BREAK o CONTINUE con una etiqueta proporciona un salto incondicional al final del bloque o del bucle asociado con esa etiqueta. Para usar una etiqueta con un bloque o un bucle, la etiqueta debe aparecer al comienzo del bloque o del ciclo y, de forma opcional, al final.
- Un nombre de etiqueta puede consistir en cualquier identificador de SQL estándar de Google, incluido el uso de tildes invertidas para incluir caracteres reservados o palabras clave.
Se pueden usar nombres de ruta de acceso multiparte, pero solo como identificadores entrecomillados.
`foo.bar`: BEGIN ... END -- Works foo.bar: BEGIN ... END -- Does not work
Los nombres de etiquetas no distinguen mayúsculas de minúsculas.
Cada procedimiento almacenado tiene un almacenamiento independiente de nombres de etiquetas. Por ejemplo, un procedimiento puede redefinir una etiqueta que ya se utiliza en un procedimiento de llamada.
Es posible que un bucle o un bloque no repita el nombre de una etiqueta que se usa en un bloque o bucle delimitador.
Los nombres de etiquetas repetidos se permiten en partes que no se superponen en las instrucciones de procedimiento.
Se permiten una etiqueta y una variable con el mismo nombre.
Cuando la declaración
BREAK
,LEAVE
,CONTINUE
oITERATE
especifica una etiqueta, sale o continúa el bucle que coincide con el nombre de la etiqueta, en lugar de elegir siempre el más interno.
Ejemplos
Solo puedes hacer referencia a un bloque o bucle mientras estés dentro de él.
label_1: BEGIN SELECT 1; BREAK label_1; SELECT 2; -- Unreached END;
label_1: LOOP BREAK label_1; END LOOP label_1; WHILE x < 1 DO CONTINUE label_1; -- Error END WHILE;
Los nombres de etiquetas repetidos se permiten en partes no superpuestas de la consulta de varias instrucciones. Esto funciona:
label_1: BEGIN BREAK label_1; END; label_2: BEGIN BREAK label_2; END; label_1: BEGIN BREAK label_1; END;
Es posible que un bucle o un bloque no repita el nombre de una etiqueta que se usa en un bloque o bucle delimitador. Se mostrará un error:
label_1: BEGIN label_1: BEGIN -- Error BREAK label_1; END; END;
Una etiqueta y una variable pueden tener el mismo nombre. Esto funciona:
label_1: BEGIN DECLARE label_1 INT64; BREAK label_1; END;
La palabra clave END
que termina un bloque o un bucle puede especificar un nombre de etiqueta, pero esto es opcional. Ambas opciones funcionan:
label_1: BEGIN BREAK label_1; END label_1;
label_1: BEGIN BREAK label_1; END;
No puedes tener una etiqueta al final de un bloque o bucle si no hay una etiqueta al comienzo del bloque o del bucle. Se mostrará un error:
BEGIN BREAK label_1; END label_1;
En este ejemplo, las instrucciones BREAK
y CONTINUE
se orientan a la label_1: LOOP
externa, en lugar del bucle WHILE x < 1 DO
interno:
label_1: LOOP WHILE x < 1 DO IF y < 1 THEN CONTINUE label_1; ELSE BREAK label_1; END WHILE; END LOOP label_1
Una declaración BREAK
, LEAVE
, CONTINUE
o ITERATE
que especifica una etiqueta que no existe muestra un error:
WHILE x < 1 DO
BREAK label_1; -- Error
END WHILE;
Se permite salir de un bloque desde la sección del controlador de excepciones:
label_1: BEGIN
SELECT 1;
EXCEPTION WHEN ERROR THEN
BREAK label_1;
SELECT 2; -- Unreached
END;
No se puede usar CONTINUE
con una etiqueta de bloque. Se mostrará un error:
label_1: BEGIN SELECT 1; CONTINUE label_1; -- Error SELECT 2; END;
Bucles
LOOP
Sintaxis
LOOP sql_statement_list END LOOP;
Descripción
Ejecuta sql_statement_list
hasta que una declaración BREAK
o LEAVE
salga del bucle. sql_statement_list
es una lista de cero o más declaraciones de SQL que terminan en punto y coma.
LOOP
no puede ejecutarse de forma dinámica como un elemento anidado. Esto
significa que LOOP
no se puede anidar en una declaración EXECUTE IMMEDIATE
.
Puedes usar una etiqueta con esta declaración. Para obtener más información, consulta Etiquetas.
Ejemplos
En el siguiente ejemplo, se declara una variable x
con el valor predeterminado 0. Luego, usa la declaración LOOP
para crear un bucle que se ejecutará hasta que la variable x
sea mayor o igual que 10; después de que se cierra el bucle, el ejemplo genera el valor de x
.
DECLARE x INT64 DEFAULT 0; LOOP SET x = x + 1; IF x >= 10 THEN LEAVE; END IF; END LOOP; SELECT x;
En este ejemplo, se muestra lo siguiente:
+----+
| x |
+----+
| 10 |
+----+
REPEAT
Sintaxis
REPEAT sql_statement_list UNTIL boolean_condition END REPEAT;
Descripción
Ejecuta de forma repetida una lista de cero o más instrucciones de SQL hasta que la condición booleana al final de la lista sea TRUE
. La condición booleana debe ser una expresión. Puedes salir de este bucle con anticipación mediante la declaración BREAK
o LEAVE
.
REPEAT
no puede ejecutarse de forma dinámica como un elemento anidado. Esto
significa que REPEAT
no se puede anidar en una declaración EXECUTE IMMEDIATE
.
Puedes usar una etiqueta con esta declaración. Para obtener más información, consulta Etiquetas.
Ejemplos
En el siguiente ejemplo, se declara una variable x
con el valor predeterminado 0
; luego, usa la declaración REPEAT
para crear un bucle que se ejecuta hasta que la variable x
sea mayor o igual que 3
.
DECLARE x INT64 DEFAULT 0; REPEAT SET x = x + 1; SELECT x; UNTIL x >= 3 END REPEAT;
En este ejemplo, se muestra lo siguiente:
+---+
| x |
+---+
| 1 |
+---+
+---+
| x |
+---+
| 2 |
+---+
+---+
| x |
+---+
| 3 |
+---+
WHILE
Sintaxis
WHILE boolean_expression DO
sql_statement_list
END WHILE;
Hay un nivel máximo de anidación de 50 para bloques y declaraciones condicionales como BEGIN
/END
, IF
/ELSE
/END IF
y WHILE
/END WHILE
.
Descripción
Mientras boolean_expression
sea verdadero, ejecuta sql_statement_list
.
boolean_expression
se evalúa para cada iteración del bucle.
WHILE
no puede ejecutarse de forma dinámica como un elemento anidado. Esto
significa que WHILE
no se puede anidar en una declaración EXECUTE IMMEDIATE
.
Puedes usar una etiqueta con esta declaración. Para obtener más información, consulta Etiquetas.
BREAK
Sintaxis
BREAK;
Description
Sale del bucle actual.
Usar BREAK
fuera de un bucle es un error.
Puedes usar una etiqueta con esta declaración. Para obtener más información, consulta Etiquetas.
Ejemplos
En el siguiente ejemplo, se declaran dos variables, heads
y heads_count
. Luego, se inicia un bucle, que asigna un valor booleano aleatorio a heads
. A continuación, verifica si heads
es verdadero; si es así, da como resultado “Heads!” (cara) y heads_count
aumenta; si no, da como resultado “Tails!” (cruz) y sale del bucle. Finalmente, da como resultado una string que indica cuántas veces el “lanzamiento de la moneda” dio como resultado “tails”.
DECLARE heads BOOL; DECLARE heads_count INT64 DEFAULT 0; LOOP SET heads = RAND() < 0.5; IF heads THEN SELECT 'Heads!'; SET heads_count = heads_count + 1; ELSE SELECT 'Tails!'; BREAK; END IF; END LOOP; SELECT CONCAT(CAST(heads_count AS STRING), ' heads in a row');
LEAVE
Sinónimo de BREAK
.
CONTINUAR
Sintaxis
CONTINUE;
Description
Omite cualquier declaración siguiente en el bucle actual y regresa al inicio del bucle.
Usar CONTINUE
fuera de un bucle es un error.
Puedes usar una etiqueta con esta declaración. Para obtener más información, consulta Etiquetas.
Ejemplos
En el siguiente ejemplo, se declaran dos variables, heads
y heads_count
. Luego, se inicia un bucle, que asigna un valor booleano aleatorio a heads
y verifica si heads
es verdadero. Si es así, el resultado es “Cara”, heads_count
aumenta y se reinicia el bucle, sin tener en cuenta las declaraciones restantes. En caso contrario, el resultado es “Sello” y sale del bucle. Finalmente, da como resultado una string que indica cuántas veces el “lanzamiento de la moneda” dio como resultado “Cara”.
DECLARE heads BOOL; DECLARE heads_count INT64 DEFAULT 0; LOOP SET heads = RAND() < 0.5; IF heads THEN SELECT 'Heads!'; SET heads_count = heads_count + 1; CONTINUE; END IF; SELECT 'Tails!'; BREAK; END LOOP; SELECT CONCAT(CAST(heads_count AS STRING), ' heads in a row');
ITERATE
Sinónimo de CONTINUE
.
FOR...IN
Sintaxis
FOR loop_variable_name IN (table_expression)
DO
sql_expression_list
END FOR;
Descripción
Repite de forma indefinida cada fila de table_expression
y la asigna a loop_variable_name
. Dentro de cada bucle, las instrucciones de SQL en sql_expression_list
se ejecutan con el valor actual de loop_variable_name
.
El valor de table_expression
se evalúa una vez al inicio del bucle. En cada iteración, el valor de loop_variable_name
es una STRUCT
que contiene las columnas de nivel superior de la expresión de la tabla como campos. El orden en el que se asignan los valores a loop_variable_name
no se define, a menos que la expresión de la tabla tenga una cláusula de nivel superior ORDER BY
o un operador de arreglo UNNEST
.
El permiso de loop_variable_name
es el cuerpo del bucle. El nombre de loop_variable_name
no puede entrar en conflicto con otras variables dentro del mismo permiso.
Puedes usar una etiqueta con esta declaración. Para obtener más información, consulta Etiquetas.
Ejemplo
FOR record IN (SELECT word, word_count FROM bigquery-public-data.samples.shakespeare LIMIT 5) DO SELECT record.word, record.word_count; END FOR;
Transacciones
COMENZAR TRANSACCIÓN
Sintaxis
BEGIN [TRANSACTION];
Description
Inicia una transacción.
La transacción finaliza cuando se alcanza una declaración COMMIT TRANSACTION
o ROLLBACK TRANSACTION
. Si la ejecución termina antes de alcanzar cualquiera de estas instrucciones, se produce una reversión automática.
Para obtener más información sobre las transacciones en BigQuery, consulta Transacciones de varias declaraciones.
Ejemplo
En el siguiente ejemplo, se realiza una transacción que selecciona filas de una tabla existente en una tabla temporal, borra esas filas de la tabla original y combina la tabla temporal con otra.
BEGIN TRANSACTION; -- Create a temporary table of new arrivals from warehouse #1 CREATE TEMP TABLE tmp AS SELECT * FROM mydataset.NewArrivals WHERE warehouse = 'warehouse #1'; -- Delete the matching records from the original table. DELETE mydataset.NewArrivals WHERE warehouse = 'warehouse #1'; -- Merge the matching records into the Inventory table. MERGE mydataset.Inventory AS I USING tmp AS T ON I.product = T.product WHEN NOT MATCHED THEN INSERT(product, quantity, supply_constrained) VALUES(product, quantity, false) WHEN MATCHED THEN UPDATE SET quantity = I.quantity + T.quantity; DROP TABLE tmp; COMMIT TRANSACTION;
CONFIRMAR TRANSACCIÓN
Sintaxis
COMMIT [TRANSACTION];
Description
Confirma una transacción abierta. Si no hay ninguna transacción abierta en curso, la declaración falla.
Para obtener más información sobre las transacciones en BigQuery, consulta Transacciones de varias declaraciones.
Ejemplo
BEGIN TRANSACTION; -- SQL statements for the transaction go here. COMMIT TRANSACTION;
REVERTIR TRANSACCIÓN
Sintaxis
ROLLBACK [TRANSACTION];
Description
Revierte una transacción abierta. Si no hay una transacción abierta en curso, la declaración falla.
Para obtener más información sobre las transacciones en BigQuery, consulta Transacciones de varias declaraciones.
Ejemplo
En el siguiente ejemplo, se revierte una transacción si se produce un error durante ella. Para ilustrar la lógica, en el ejemplo se activa un error de dividir por cero después de insertar una fila en una tabla. Una vez que se ejecutan estas declaraciones, la tabla no se ve afectada.
BEGIN BEGIN TRANSACTION; INSERT INTO mydataset.NewArrivals VALUES ('top load washer', 100, 'warehouse #1'); -- Trigger an error. SELECT 1/0; COMMIT TRANSACTION; EXCEPTION WHEN ERROR THEN -- Roll back the transaction inside the exception handler. SELECT @@error.message; ROLLBACK TRANSACTION; END;
RAISE
Sintaxis
RAISE [USING MESSAGE = message];
Descripción
Genera un error y usa, de manera opcional, el mensaje de error especificado cuando se proporciona USING
MESSAGE = message
.
Cuando no se proporciona USING MESSAGE
Solo se debe usar la declaración RAISE
dentro de una cláusula EXCEPTION
. La declaración RAISE
generará nuevamente la excepción que se capturó y conservará el seguimiento de pila original.
Cuando se proporciona USING MESSAGE
Si la declaración RAISE
se encuentra dentro de la sección BEGIN
de un bloque BEGIN...EXCEPTION
, ocurrirá lo siguiente:
- Se invocará al controlador.
El valor de
@@error.message
coincidirá exactamente con la stringmessage
proporcionada (que puede serNULL
simessage
esNULL
).Se establecerá el seguimiento de pila en la declaración
RAISE
.
Si la instrucción RAISE
no se encuentra dentro de la sección BEGIN
de un bloque BEGIN...EXCEPTION
, la instrucción RAISE
detendrá la ejecución de la consulta de varias instrucciones con el mensaje de error suministrado.
RETURN
RETURN
detiene la ejecución de la consulta de varias instrucciones.
CALL
Sintaxis
CALL procedure_name (procedure_argument[, …])
Descripción
Llama a un procedimiento con una lista de argumentos.
procedure_argument
puede ser una variable o una expresión. Para los argumentos OUT
o INOUT
, una variable pasada como argumento debe tener el tipo apropiado de SQL estándar de Google.
Es posible que la misma variable no aparezca varias veces como un argumento OUT
o INOUT
en la lista de argumentos del procedimiento.
La profundidad máxima de las llamadas a procedimiento es de 50 fotogramas.
CALL
no puede ejecutarse de forma dinámica como un elemento anidado. Esto
significa que CALL
no se puede anidar en una declaración EXECUTE IMMEDIATE
.
Ejemplos
En el siguiente ejemplo, se declara una variable retCode
. Luego, llama al procedimiento updateSomeTables
en el conjunto de datos myDataset
, pasando los argumentos 'someAccountId'
y retCode
. Por último, muestra el valor de retCode
.
DECLARE retCode INT64;
-- Procedure signature: (IN account_id STRING, OUT retCode INT64)
CALL myDataset.UpdateSomeTables('someAccountId', retCode);
SELECT retCode;