Estrutura e sintaxe lexicais

Uma instrução SQL do Cloud Spanner é composta por uma série de tokens. Eles incluem identificadores, identificadores entre aspas, literais, palavras-chave, operadores e caracteres especiais. Os tokens podem ser separados por espaços em branco (espaço, backspace, tabulação, nova linha) ou comentários.

Identificadores

São nomes associados a colunas, tabelas e outros objetos do banco de dados.

Precisam começar com uma letra ou um sublinhado. Os caracteres seguintes podem ser letras, números ou sublinhados. Identificadores entre aspas são os que ficam entre os caracteres de crase (`) e podem conter qualquer caractere, como espaços ou símbolos. De qualquer maneira, não podem ficar vazios. As palavras-chave reservadas só podem ser usadas como identificadores se estiverem entre crases.

Sintaxe (definida aqui como uma expressão regular):

[A-Za-z_][A-Za-z_0-9]*

Exemplos:

Customers5
_dataField1
ADGROUP

Exemplos inválidos:

5Customers
_dataField!
GROUP

5Customers começa com um número, não uma letra ou um sublinhado. _dataField! contém o caractere especial "!" que não é uma letra, um número ou um sublinhado. GROUP é uma palavra-chave reservada e, portanto, não pode ser usada como identificador sem estar entre caracteres de crase.

Tanto os identificadores como os identificadores entre aspas não diferenciam maiúsculas de minúsculas, com pequenas diferenças. Veja mais detalhes em Diferenciação entre maiúsculas e minúsculas.

Os identificadores entre aspas têm as mesmas sequências de escape que os literais de strings, definidos a seguir.

Literais

Os literais representam um valor constante de um tipo de dados integrado. Alguns tipos de dados podem ser expressos como literais, mas nem todos.

Literais de strings e bytes

Os literais de string e de bytes precisam ficar entre aspas, com aspas simples (') ou duplas (") ou, ainda, aspas triplas com grupos de três aspas simples (''') ou três duplas (""").

Literais entre aspas:

Literal Exemplos Descrição
String entre aspas
  • "abc"
  • "it's"
  • 'it\'s'
  • 'Title: "Boy"'
Strings entre aspas simples (') podem conter aspas duplas sem escape ("), assim como o inverso. As
barras invertidas (\) iniciam as sequências de escape. Veja a tabela "Sequências de escape" abaixo.
As strings entre aspas não podem ter novas linhas, mesmo se precedidas de barra invertida (\).
String entre três aspas
  • """abc"""
  • '''it's'''
  • '''Title:"Boy"'''
  • '''two
    lines'''
  • '''why\?'''
As novas linhas e aspas incorporadas são permitidas sem escapes. Veja o quarto exemplo. As
barras invertidas (\) iniciam as sequências de escape. Veja a tabela "Sequências de escape" abaixo.
Não é permitida uma barra invertida (\) sem escape no final de uma linha.
Encerre a string com três aspas sem escape em uma linha que correspondam às aspas iniciais.
String bruta
  • R"abc+"
  • r'''abc+'''
  • R"""abc+"""
  • r'f\(abc,(.*),def\)'
Os literais entre aspas ou aspas triplas que têm o prefixo do literal de string bruta (r ou R) são interpretados como strings brutas/regex.
Os caracteres de barra invertida (\) não funcionam como caracteres de escape. Se uma barra invertida seguida por outro caractere for usada dentro do literal de string, os dois caracteres serão preservados.
As strings brutas não podem terminar com um número ímpar de barras invertidas.
As strings brutas são úteis para construir expressões regulares.

Os caracteres de prefixo (r, R, b, B)) são opcionais para strings entre aspas ou três aspas e indicam que a string é do tipo bruta/regex ou uma sequência de bytes, respectivamente. Por exemplo, b'abc' e b'''abc''' são interpretados como bytes de tipo. Os caracteres de prefixo diferenciam maiúsculas de minúsculas.

Literais entre aspas com prefixos:

Literal Exemplo Descrição
Bytes
  • B"abc"
  • B'''abc'''
  • b"""abc"""
Os literais entre aspas ou aspas triplas com o prefixo de literal de bytes (b ou B) são interpretados como bytes.
Bytes brutos
  • br'abc+'
  • RB"abc+"
  • RB'''abc'''
Os prefixos r e b podem ser combinados em qualquer ordem. Por exemplo, rb'abc*' equivale a br'abc*'.

Na tabela a seguir, veja todas as sequências de escape válidas para representar caracteres não alfanuméricos em literais de strings e bytes. Qualquer sequência que não esteja nesta tabela resulta em erro.

Sequência de escape Descrição
\a Aviso sonoro
\b Backspace
\f Avanço de formulário
\n Nova linha
\r Retorno de carro
\t Tabulação
\v Tabulação vertical
\\ Barra invertida (\)
\? Ponto de interrogação (?)
\" Aspas duplas (")
\' Aspas simples (')
\` Crase (`)
\ooo Escape octal, com exatamente três dígitos (no intervalo de 0 a 7). É decodificado como um único caractere Unicode (em literais de strings) ou byte (em literais de bytes).
\xhh ou \Xhh Escape hexadecimal, com exatamente dois dígitos hexadecimais (0–9 ou A–F ou a–f). É decodificado como um único caractere Unicode (em literais de strings) ou byte (em literais de bytes). Exemplos:
  • '\x41' == 'A'
  • '\x41B' é 'AB'
  • '\x4' é um erro
\uhhhh Escape Unicode, com "u" minúsculo e exatamente quatro dígitos hexadecimais. Válido apenas em literais de string ou identificadores.
Observação: o intervalo D800-DFFF não é permitido, já que são valores unicode alternativos.
\Uhhhhhhhh Escape Unicode, com "U" maiúsculo e exatamente oito dígitos hexadecimais. Válido apenas em literais de string ou identificadores.
O intervalo D800-DFFF não é permitido, pois são valores unicode alternativos. Além disso, valores maiores que 10FFFF não são permitidos.

Literais de inteiros

Literais de inteiros são uma sequência de dígitos decimais (de 0 a 9) ou um valor hexadecimal com prefixo "0x" ou "0X". Os inteiros podem ter o prefixo "+" ou "-" para representar valores positivos e negativos, respectivamente. Exemplos:

123
0xABC
-123

Um literal de inteiro é interpretado como INT64.

Literais de ponto flutuante

Opções de sintaxe:

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

DIGITS representa um número decimal (de 0 a 9) ou mais, e e representa o rótulo expoente (e ou E).

Exemplos:

123.456e-67
.1E4
58.
4e2

Supõe-se que os literais numéricos que contêm um ponto decimal ou um rótulo expoente sejam do tipo duplo.

A coerção implícita de literais de ponto flutuante para o tipo flutuante será possível se o valor estiver dentro do intervalo flutuante válido.

Não há representação literal de NaN ou infinitude, mas é possível fazer o cast para flutuante das strings que diferenciam entre maiúsculas e minúsculas a seguir:

  • "NaN"
  • "inf" ou "+inf"
  • "-inf"

Literais de matriz

Literais de matriz são listas separadas por vírgulas de elementos entre colchetes. A palavra-chave ARRAY é opcional, assim como um tipo de elemento T explícito.

Exemplos:

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

Literais struct

Sintaxe:

(elem[, elem...])

em que elemé um elemento no struct. precisa ser um tipo de dados de literal, não uma expressão ou nome de coluna.

O tipo de saída é de struct anônimo (structs são tipos não nomeados) com campos anônimos contendo tipos que correspondem aos existentes nas expressões de entrada.

Exemplo Tipo de saída
(1, 2, 3) STRUCT<int64,int64,int64>
(1, 'abc') STRUCT<int64,string>

Literais de data

Sintaxe:

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

Literais de data contêm a palavra-chave DATE seguida de um literal de string em conformidade com o formato de data canônico e ficam entre aspas simples. Os literais de data, inclusive, aceitam um intervalo entre os anos 1 e 9999. As datas fora desse intervalo são inválidas.

Por exemplo, o literal de data a seguir representa 27 de setembro de 2014:

DATE '2014-09-27'

Os literais de strings no formato de data canônico também forçam, implicitamente, o tipo DATE quando usados se uma expressão do tipo DATE for esperada. Por exemplo, na consulta

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

o literal de string "2014-09-27" será forçado para um literal de data.

Literais de carimbo de data/hora

Sintaxe:

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

Os literais de carimbo de data/hora contêm a palavra-chave TIMESTAMP e um literal de string em conformidade com o formato de carimbo de data/hora canônico e ficam entre aspas simples.

Os literais de carimbo de data/hora aceitam um intervalo entre os anos 1 e 9999, inclusive. Carimbos de data/hora fora desse intervalo são inválidos.

Um literal de carimbo de data/hora pode incluir um sufixo numérico para indicar o fuso horário:

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

Se esse sufixo estiver ausente, o fuso horário padrão, "América/Los Angeles", será usado.

Por exemplo, este carimbo de data/hora representa 12h30 do dia 27 de setembro de 2014, usando o fuso horário "América/Los Angeles":

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

Para ver mais informações de fusos horários, veja Fuso horário.

Literais de string com o formato de carimbo de data/hora canônico, incluindo aqueles com nomes de fusos horários, forçam implicitamente um literal de carimbo de data/hora quando usados se uma expressão de carimbo de data/hora for esperada. Por exemplo, na consulta a seguir, o literal de string "2014-09-27 12:30:00.45 America/Los_Angeles" é forçado para um literal de carimbo de data/hora.

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

Fuso horário

Devido à obrigatoriedade de mapear os literais de carimbo de data/hora para um ponto específico no tempo, um fuso horário é necessário para interpretar corretamente um literal. Se um fuso horário não for especificado como parte do literal propriamente dito, o SQL do Cloud Spanner usará o valor de fuso horário padrão definido pela implementação SQL do Cloud Spanner.

O SQL do Cloud Spanner representa os fusos horários usando strings no seguinte formato canônico, que representa o deslocamento do tempo universal coordenado (UTC).

Formato:

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

Exemplos:

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

Os fusos horários também podem ser expressos com strings de nomes de fusos horários do tz database. Para ter uma referência menos explicativa, porém mais simples, veja a Lista de fusos horários do tz database (em inglês) na Wikipédia. Os nomes de fusos horários canônicos têm o formato <continent/[region/]city>, como America/Los_Angeles.

Observação: nem todos os nomes de fuso horário são intercambiáveis, mesmo que mostrem o mesmo horário durante uma estação do ano. Por exemplo, America/Los_Angeles mostra o mesmo horário de UTC-7:00 durante horários de verão e o mesmo horário de UTC-8:00 quando não está no horário de verão.

Exemplo:

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

Diferenciação entre maiúsculas e minúsculas

O Cloud Spanner SQL segue estas regras para diferenciar maiúsculas de minúsculas:

Categoria Diferenciação entre maiúsculas e minúsculas? Observações
Palavras-chave Não  
Nomes de funções Não  
Nomes de tabela Consulte as observações Os nomes de tabela geralmente não diferenciam maiúsculas de minúsculas, mas podem diferenciar quando se consulta um banco de dados que usa nomes de tabela com essa diferenciação.
Nomes de coluna Não  
Valores de strings Sim
Comparações de strings Sim  
Aliases dentro de uma consulta Não  
Correspondência com expressões regulares Consulte as observações A expressão regular correspondente diferencia maiúsculas de minúsculas por padrão, a menos que a própria expressão especifique que ela não pode fazer essa diferenciação.
Correspondência com LIKE Sim  

Palavras-chave reservadas

Palavras-chave são um grupo de tokens que têm um significado especial na linguagem Cloud Spanner SQL e as seguintes características:

  • Não é possível usar palavras-chave como identificadores a menos que estejam entre caracteres de acento grave (`).
  • As palavras-chave não diferenciam maiúsculas de minúsculas.

O SQL do Cloud Spanner tem as seguintes palavras-chave 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

Ponto e vírgula de terminação

Como opção, as instruções de string de consulta podem terminar com ponto e vírgula (;) quando enviadas por meio da Interface de Programação do Aplicativo (API).

Em solicitações com várias instruções, elas precisam ser separadas por ponto e vírgula, que costuma ser opcional após a instrução final. Em algumas ferramentas interativas, é necessário que as instruções terminem com ponto e vírgula.

Parâmetros de consulta

Sintaxe:

@param

Os parâmetros de consulta são denotados por identificadores precedidos pelo caractere @. Defina o parâmetro fora da instrução de consulta.

Use parâmetros de consulta para substituir expressões arbitrárias. No entanto, os parâmetros de consulta não podem ser usados para substituir identificadores, nomes de colunas, nomes de tabelas ou outras partes da própria consulta.

As APIs de cliente permitem a vinculação de nomes de parâmetros a valores; a API do cliente substitui o valor limite do parâmetro no momento da execução. Algumas APIs de cliente permitem consultas com parâmetros que não estão vinculados a valores específicos, mas, nesses casos, defina o tipo de parâmetro no momento da análise da consulta.

Exemplo:

SELECT * FROM Roster WHERE LastName = @myparam

retorna todas as linhas em que LastName é igual ao valor do parâmetro de consulta myparam.

Comentários

Comentários são sequências de caracteres ignoradas pelo analisador. O SQL do Cloud Spanner é compatível com os seguintes tipos de comentários.

Comentários de linha única

Use um comentário de linha única se quiser que o comentário apareça apenas em uma linha.

Exemplos

# 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";

Comentários in-line

Use um comentário in-line se quiser que ele apareça na mesma linha da instrução. Comentários precedidos por # ou -- têm que aparecer à direita das instruções.

Exemplos

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";

Comentários de várias linhas

Use um comentário de várias linhas se precisar que o comentário inclua várias linhas. Comentários de várias linhas aninhados não são compatíveis.

Exemplos

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";