Estructura léxica y sintaxis

Una instrucción de SQL de Cloud Spanner consta de una serie de tokens. Los tokens incluyen identificadores, identificadores entrecomillados, literales, palabras clave, operadores y caracteres especiales. Puedes separar tokens con espacios en blanco (por ejemplo, espacio, retroceso, tabulación, nueva línea) o comentarios.

Identificadores

Los identificadores son nombres asociados con columnas, tablas y otros objetos de base de datos. Pueden estar entre comillas o sin ellas.

  • Los identificadores se pueden usar en expresiones de ruta que muestran una STRUCT.
  • Algunos identificadores distinguen entre mayúsculas y minúsculas y otros no. Para obtener más información, consulta Distinción entre mayúsculas y minúsculas.
  • Los identificadores sin comillas deben comenzar con una letra o un carácter de guion bajo. Los caracteres que le siguen pueden ser letras, números o guiones bajos.
  • Los identificadores entrecomillados deben estar encerrados entre caracteres de acento grave (`).
    • Los identificadores entrecomillados pueden contener cualquier carácter, como espacios o símbolos.
    • Los identificadores entrecomillados no pueden estar vacíos.
    • Los identificadores entrecomillados tienen las mismas secuencias de escape que los literales de string.
    • Una palabra clave reservada debe ser un identificador entrecomillado si es una palabra clave independiente o el primer componente de una expresión de ruta. Puede no estar entrecomillado si es el segundo componente de una expresión de ruta o un componente posterior.

Ejemplos

Estos son identificadores válidos:

Customers5
`5Customers`
dataField
_dataField1
ADGROUP
`tableName~`
`GROUP`

Estas expresiones de ruta de acceso contienen identificadores válidos:

foo.`GROUP`
foo.GROUP
foo().dataField
list[OFFSET(3)].dataField
list[ORDINAL(3)].dataField
@parameter.dataField

Estos son identificadores no válidos:

5Customers
_dataField!
GROUP

5Customers comienza con un número, no con una letra o guion bajo. _dataField! contiene el carácter especial “!” que no es una letra, número o guion bajo. GROUP es una palabra clave reservada y, por lo tanto, no se puede usar como un identificador si no está encerrada entre caracteres de acento grave.

Literales

Un literal representa un valor constante de un tipo de datos integrado. Algunos tipos de datos pueden expresarse como literales, pero no todos.

Literales de string y de bytes

Los literales de string y de bytes deben estar entre comillas simples (') o dobles ("), o entre comillas triples con grupos de tres comillas simples (''') o tres dobles (""").

Literales entrecomillados:

Literal Ejemplos Descripción
String entrecomillada
  • "abc"
  • "it's"
  • 'it\'s'
  • 'Title: "Boy"'
Las strings encerradas entre comillas simples (') pueden contener comillas dobles (") sin escapar y viceversa.
Las barras invertidas (\) ingresan secuencias de escape. Consulta la tabla Secuencias de escape a continuación.
Las strings entre comillas no pueden contener líneas nuevas, ni siquiera cuando las precede una barra invertida (\).
String entre comillas triples
  • """abc"""
  • '''it's'''
  • '''Title:"Boy"'''
  • '''two
    lines'''
  • '''why\?'''
Se permiten caracteres de línea nueva incrustados y comillas sin escapar; consulta el cuarto ejemplo.
Las barras invertidas (\) ingresan secuencias de escape. Consulta la tabla Secuencias de escape a continuación.
No se permite una barra invertida sin escape (\) al final de una línea.
Debes terminar la string con tres comillas sin escapar seguidas que coincidan con las comillas iniciales.
String sin procesar
  • R"abc+"
  • r'''abc+'''
  • R"""abc+"""
  • r'f\(abc,(.*),def\)'
Los literales con comillas o comillas triples que tienen el prefijo literal de string sin procesar (r o R) se interpretan como strings sin procesar o de expresión regular.
Los caracteres de barra invertida (\) no actúan como caracteres de escape. Si una barra invertida seguida de otro carácter aparece dentro del literal de string, se conservan ambos caracteres.
Una string sin procesar no puede terminar con un número impar de barras invertidas.
Las strings sin procesar son útiles para construir expresiones regulares.

Los caracteres de prefijo (r, R, b, B)) son opcionales para strings entre comillas o comillas triples y, además, indican que la string es una string sin procesar o de expresión regular, o bien una secuencia de bytes, respectivamente. Por ejemplo, b'abc' y b'''abc''' se interpretan como de tipo byte. Los caracteres de prefijo no distinguen entre mayúsculas y minúsculas.

Literales entrecomillados con prefijos:

Literal Ejemplo Descripción
Bytes
  • B"abc"
  • B'''abc'''
  • b"""abc"""
Los literales con comillas o comillas triples que tienen el prefijo de literal de bytes (b o B) se interpretan como bytes.
Bytes sin procesar
  • br'abc+'
  • RB"abc+"
  • RB'''abc'''
Los prefijos r y b se pueden combinar en cualquier orden. Por ejemplo, rb'abc*' es equivalente a br'abc*'.

En la siguiente tabla, se enumeran todas las secuencias de escape válidas para representar caracteres no alfanuméricos en literales de string y de bytes. Cualquier secuencia que no esté en esta tabla genera un error.

Secuencia de escape Descripción
\a Bell
\b Retroceso
\f Salto de página
\n Nueva línea
\r Retorno de carro
\t Tabulación
\v Tabulación vertical
\\ Barra invertida (\)
\? Signo de interrogación (?)
\" Comillas dobles (")
\' Comillas simples (')
\` Acento grave (`)
\ooo Escape octal con 3 dígitos (en el rango 0–7). Se decodifica como solo carácter Unicode (en literales de string) o byte (en literales de bytes).
\xhh o \Xhh Escape hexadecimal con 2 dígitos hexadecimales (0–9 y A–F o a–f). Se decodifica como solo carácter Unicode (en literales de string) o byte (en literales de bytes). Por ejemplo:
  • '\x41' == 'A'
  • '\x41B' es 'AB'
  • '\x4' es un error
\uhhhh Escape de Unicode, con una “u” en minúscula y 4 dígitos hexadecimales. Solo es válido en literales de string o identificadores.
Ten en cuenta que el rango D800-DFFF no está permitido, ya que estos son valores unicode subrogados.
\Uhhhhhhhh Escape de Unicode, con una “U” mayúscula y 8 dígitos hexadecimales. Válido solo en literales de string o identificadores.
El rango D800-DFFF no está permitido, ya que estos valores son valores unicode subrogados. Además, no se permiten valores superiores a 10FFFF.

Literales de número entero

Los literales de números enteros son una secuencia de dígitos decimales (0-9) o un valor hexadecimal con el prefijo “0x” o “0X”. Los números enteros pueden tener el prefijo “+” o “-” para representar los valores positivos y negativos, respectivamente. Por ejemplo:

123
0xABC
-123

Un literal de número entero se interpreta como INT64.

Literales de punto flotante

Opciones de sintaxis:

[+-]DIGITS.[DIGITS][e[+-]DIGITS]
[DIGITS].DIGITS[e[+-]DIGITS]
DIGITSe[+-]DIGITS

DIGITS representa uno o más números decimales (0 a 9) y e representa el marcador de exponente (e o E).

Por ejemplo:

123.456e-67
.1E4
58.
4e2

Se supone que los literales numéricos que contienen un punto decimal o un marcador de exponente son de tipo doble.

Es posible la conversión implícita de los literales de punto flotante en tipo flotante si el valor está dentro del rango flotante válido.

No hay una representación literal de NaN o infinito, pero las siguientes string sin distinción entre mayúsculas y minúsculas se pueden convertir de forma explícita en flotantes:

  • “NaN”
  • “inf” o “+inf”
  • “-inf”

Literales de arreglo

Los literales de arreglo son listas de elementos separados por comas entre corchetes. La palabra clave ARRAY y un tipo de elemento T explícito son opcionales.

Por ejemplo:

[1, 2, 3]
['x', 'y', 'xy']
ARRAY[1, 2, 3]
ARRAY<string>['x', 'y', 'xy']
ARRAY<int64>[]

Literales de struct

Sintaxis:

(elem[, elem...])

En el ejemplo anterior, elem es un elemento de struct y elem debe ser un tipo de datos literal, no una expresión o nombre de columna.

El resultado tiene un tipo de struct anónimo (los structs no son tipos con nombre) con campos anónimos que tienen tipos que coinciden con los de las expresiones de entrada.

Ejemplo Tipo de salida
(1, 2, 3) STRUCT<int64,int64,int64>
(1, 'abc') STRUCT<int64,string>

Literales de fecha

Sintaxis:

DATE 'YYYY-M[M]-D[D]'

Los literales de fecha contienen la palabra clave DATE seguida de un literal de string que se ajusta al formato de fecha canónico y está encerrado entre comillas simples. Los literales de fecha admiten un rango entre los años 1 y 9999, inclusive. Las fechas fuera de este rango no son válidas.

Por ejemplo, el siguiente literal de fecha representa el 27 de septiembre de 2014:

DATE '2014-09-27'

Los literales de string en formato de fecha canónico también se convierten de forma implícita en el tipo DATE si se usan cuando se espera una expresión de tipo DATE. Por ejemplo, en la consulta siguiente:

SELECT * FROM foo WHERE date_col = "2014-09-27"

el literal de string "2014-09-27" se convertirá en un literal de fecha.

Literales de marca de tiempo

Sintaxis:

TIMESTAMP 'YYYY-[M]M-[D]D [[H]H:[M]M:[S]S[.DDDDDD] [timezone]]`

Los literales de marca de tiempo contienen la palabra clave TIMESTAMP y un literal de string que se ajusta al formato de marca de tiempo canónico y está encerrado entre comillas simples.

Los literales de marca de tiempo admiten un rango entre los años 1 y 9999, inclusive. Las marcas de tiempo fuera de este rango no son válidas.

Un literal de marca de tiempo puede incluir un sufijo numérico para indicar la zona horaria:

TIMESTAMP '2014-09-27 12:30:00.45-08'

Si no aparece este sufijo, se usa la zona horaria predeterminada, America/Los_Angeles.

Por ejemplo, la siguiente marca de tiempo representa las 12:30 p.m. del 27 de septiembre de 2014 con la zona horaria America/Los_Angeles:

TIMESTAMP '2014-09-27 12:30:00.45'

Consulta las zonas horarias para obtener más información.

Los literales de string con el formato de marca de tiempo canónico, incluidos los que tienen nombres de zona horaria, se convierten de forma implícita en un literal de marca de tiempo si se usan cuando se espera una expresión de marca de tiempo. Por ejemplo, en la siguiente consulta, el literal de string "2014-09-27 12:30:00.45 America/Los_Angeles" se convierte en un literal de marca de tiempo.

SELECT * FROM foo
WHERE timestamp_col = "2014-09-27 12:30:00.45 America/Los_Angeles"

Un literal de marca de tiempo puede incluir estos caracteres opcionales:

  • T o t: una marca de tiempo. Se usa como separador entre la fecha y la hora.
  • Z o z: una marca para la zona horaria predeterminada. No se puede usar con [timezone].

Si usas uno de estos caracteres, no se puede incluir un espacio ni antes ni después. Los siguientes literales son válidos:

TIMESTAMP '2017-01-18T12:34:56.123456Z'
TIMESTAMP '2017-01-18t12:34:56.123456'
TIMESTAMP '2017-01-18 12:34:56.123456z'
TIMESTAMP '2017-01-18 12:34:56.123456Z'

Zona horaria

Debido a que los literales de marca de tiempo deben asignarse a un momento específico, se necesita una zona horaria para interpretarlos de forma correcta. Si no se especifica una zona horaria como parte del literal, SQL de Cloud Spanner usa el valor de zona horaria predeterminado que se establece con la implementación de SQL de Cloud Spanner.

SQL de Cloud Spanner representa zonas horarias mediante strings en el siguiente formato canónico, que representa la diferencia con el tiempo universal coordinado (UTC).

Formato:

(+|-)H[H][:M[M]]

Por ejemplo:

'-08:00'
'-8:15'
'+3:00'
'+07:30'
'-7'

Las zonas horarias también se pueden expresar mediante nombres de zona horaria de string de la base de datos tz. Si prefieres una referencia menos completa, pero más simple, consulta la lista de zonas horarias de la base de datos tz en Wikipedia. Los nombres de zonas horarias canónicos tienen el formato <continent/[region/]city>, como America/Los_Angeles.

Ejemplo:

TIMESTAMP '2014-09-27 12:30:00 America/Los_Angeles'
TIMESTAMP '2014-09-27 12:30:00 America/Argentina/Buenos_Aires'

Distinción entre mayúsculas y minúsculas

SQL de Cloud Spanner sigue estas reglas para la distinción entre mayúsculas y minúsculas:

Categoría ¿Distingue mayúsculas de minúsculas? Notas
Palabras clave No  
Nombres de funciones No  
Nombres de tablas Ver las notas Por lo general, los nombres de tablas no distinguen entre mayúsculas y minúsculas, pero pueden distinguirlas cuando se consulta una base de datos que usa nombres de tablas que distinguen mayúsculas de minúsculas.
Nombres de columnas No  
Valores de string
Comparaciones de strings  
Alias dentro de una consulta No  
Coincidencia de expresiones regulares Ver las notas La coincidencia de expresiones regulares distingue entre mayúsculas y minúsculas de forma predeterminada, a menos que la expresión misma especifique que no realiza esta distinción.
Coincidencia de LIKE  

Palabras clave reservadas

Las palabras clave son un grupo de tokens que tienen un significado especial en el lenguaje SQL de Cloud Spanner y tienen las siguientes características:

  • Las palabras clave no se pueden usar como identificadores, a menos que estén encerradas entre caracteres de acento grave (`).
  • Las palabras clave no distinguen entre mayúsculas y minúsculas.

SQL de Cloud Spanner tiene las siguientes palabras clave reservadas.

ALL
AND
ANY
ARRAY
AS
ASC
ASSERT_ROWS_MODIFIED
AT
BETWEEN
BY
CASE
CAST
COLLATE
CONTAINS
CREATE
CROSS
CUBE
CURRENT
DEFAULT
DEFINE
DESC
DISTINCT
ELSE
END
ENUM
ESCAPE
EXCEPT
EXCLUDE
EXISTS
EXTRACT
FALSE
FETCH
FOLLOWING
FOR
FROM
FULL
GROUP
GROUPING
GROUPS
HASH
HAVING
IF
IGNORE
IN
INNER
INTERSECT
INTERVAL
INTO
IS
JOIN
LATERAL
LEFT
LIKE
LIMIT
LOOKUP
MERGE
NATURAL
NEW
NO
NOT
NULL
NULLS
OF
ON
OR
ORDER
OUTER
OVER
PARTITION
PRECEDING
PROTO
RANGE
RECURSIVE
RESPECT
RIGHT
ROLLUP
ROWS
SELECT
SET
SOME
STRUCT
TABLESAMPLE
THEN
TO
TREAT
TRUE
UNBOUNDED
UNION
UNNEST
USING
WHEN
WHERE
WINDOW
WITH
WITHIN

Punto y coma final

De forma opcional, puedes usar un punto y coma final (;) cuando envíes una instrucción de string de consulta a través de una interfaz de programación de aplicaciones (API).

En una solicitud que contiene múltiples instrucciones, debes separarlas con punto y coma, pero, por lo general, este símbolo es opcional después de la instrucción final. Algunas herramientas interactivas requieren que las instrucciones tengan un punto y coma final.

Comas finales

De manera opcional, puedes usar una coma final (,) luego de una lista en una declaración SELECT.

Ejemplo

SELECT name, release_date, FROM Books

Parámetros de consulta

Puedes usar parámetros de consulta para sustituir expresiones arbitrarias. Sin embargo, los parámetros de consulta no se pueden usar para sustituir identificadores, nombres de columnas, nombres de tablas ni otras partes de la consulta. Los parámetros de consulta se definen fuera de la declaración de consulta.

Las API de cliente permiten la vinculación de nombres de parámetros a valores; el motor de consultas sustituye un valor vinculado por un parámetro en el momento de la ejecución.

Parámetros de consulta con nombre

Sintaxis:

@parameter_name

Un parámetro de consulta con nombre se denota mediante un identificador precedido por el carácter @.

Ejemplo:

En este ejemplo, se muestran todas las filas en las que LastName es igual al valor del parámetro de consulta con nombre myparam.

SELECT * FROM Roster WHERE LastName = @myparam

Sugerencias

@{ hint [, ...] }

hint:
  [engine_name.]hint_name = value

El objetivo de una sugerencia es modificar la estrategia de ejecución para una consulta sin cambiar el resultado de la consulta. Las sugerencias, por lo general, no afectan la semántica de las consultas, pero pueden tener implicaciones en el rendimiento. Están disponibles los siguientes tipos de sugerencias:

La sintaxis de sugerencias requiere el carácter @ seguido de llaves. Puedes crear una sugerencia o un grupo de sugerencias. El prefijo engine_name. opcional permite que varios motores definan las sugerencias con el mismo hint_name. Esto es importante si necesitas sugerir diferentes estrategias de ejecución específicas por motor o hay motores diferentes que admiten sugerencias diferentes.

Puedes asignar identificadores y literales a las sugerencias.

  • Los identificadores son útiles para sugerencias que actúan como enumeraciones. Puedes usar un identificador para evitar usar una string entre comillas. En el AST resuelto, las sugerencias de identificadores se representan como literales de string, por lo que @{hint="abc"} es lo mismo que @{hint=abc}. Las sugerencias de identificadores también se pueden usar para sugerencias que toman un nombre de tabla o un nombre de columna como un identificador único.
  • Los literales NULL se permiten y se infieren como números enteros.

Las sugerencias deben aplicarse solo al nodo al que están conectadas y no a un permiso mayor. Por ejemplo, una sugerencia en un JOIN en el medio de la cláusula FROM está destinada a aplicarse solo a esa JOIN y no a otras JOIN en la cláusula FROM. Las sugerencias a nivel de la declaración se pueden usar para las sugerencias que modifican la ejecución de una declaración completa, por ejemplo, un presupuesto de la memoria general o un plazo.

Ejemplos

En este ejemplo, se asigna un literal a una sugerencia. Esta sugerencia solo se usa con dos motores de bases de datos llamados database_engine_a y database_engine_b. El valor de la sugerencia es diferente para cada motor de base de datos.

@{ database_engine_a.file_count=23, database_engine_b.file_count=10 }

En este ejemplo, se asigna un identificador a una pista. Hay identificadores únicos para cada tipo de sugerencia. Puedes ver una lista de tipos de sugerencias al principio de este tema.

@{ JOIN_METHOD=HASH_JOIN }

Comentarios

Los comentarios son secuencias de caracteres que el analizador ignora. SQL de Cloud Spanner admite los siguientes tipos de comentarios.

Comentarios de una línea

Usa un comentario de una línea si deseas que aparezca en una línea solo.

Ejemplos

# this is a single-line comment
SELECT book FROM library;
-- this is a single-line comment
SELECT book FROM library;
/* this is a single-line comment */
SELECT book FROM library;
SELECT book FROM library
/* this is a single-line comment */
WHERE book = "Ulysses";

Comentarios intercalados

Usa un comentario intercalado si deseas que aparezca en la misma línea que una instrucción. Un comentario precedido por # o -- debe aparecer a la derecha de una instrucción.

Ejemplos

SELECT book FROM library; # this is an inline comment
SELECT book FROM library; -- this is an inline comment
SELECT book FROM library; /* this is an inline comment */
SELECT book FROM library /* this is an inline comment */ WHERE book = "Ulysses";

Comentarios de varias líneas

Usa un comentario de varias líneas si necesitas que abarque múltiples líneas. No se admiten los comentarios de varias líneas anidados.

Ejemplos

SELECT book FROM library
/*
  This is a multiline comment
  on multiple lines
*/
WHERE book = "Ulysses";
SELECT book FROM library
/* this is a multiline comment
on two lines */
WHERE book = "Ulysses";