Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

Sintaxe

Nesta seção, vamos examinar a sintaxe SQL do ClickHouse. O ClickHouse usa uma sintaxe baseada em SQL, mas oferece diversas extensões e otimizações.

Análise sintática de consultas

Há dois tipos de parsers no ClickHouse:

  • Um parser SQL completo (um parser por descida recursiva).
  • Um parser de formato de dados (um parser de fluxo rápido).

O parser SQL completo é usado em todos os casos, exceto na consulta INSERT, que usa ambos os parsers.

Vamos examinar a consulta abaixo:

INSERT INTO t VALUES (1, 'Hello, world'), (2, 'abc'), (3, 'def')

Como já mencionado, a consulta INSERT usa ambos os parsers. O fragmento INSERT INTO t VALUES é analisado pelo parser completo, e os dados (1, 'Hello, world'), (2, 'abc'), (3, 'def') são analisados pelo parser de formato de dados, ou parser rápido de fluxo.

Ativando o parser completo

Você também pode ativar o parser completo para os dados usando a configuração input_format_values_interpret_expressions.

Quando a configuração mencionada acima é definida como 1, o ClickHouse primeiro tenta analisar os valores com o parser rápido de fluxo. Se isso falhar, o ClickHouse tenta usar o parser completo para os dados, tratando-os como uma expressão SQL.

Os dados podem estar em qualquer formato. Quando uma consulta é recebida, o servidor mantém no máximo max_query_size bytes da solicitação em RAM (por padrão, 1 MB), e o restante é analisado em fluxo. Isso ajuda a evitar problemas com consultas INSERT grandes, que é a forma recomendada de inserir seus dados no ClickHouse.

Ao usar o formato Values em uma consulta INSERT, pode parecer que os dados são analisados da mesma forma que as expressões em uma consulta SELECT, mas não é esse o caso. O formato Values é muito mais limitado.

O restante desta seção aborda o parser completo.

Espaços

  • Pode haver qualquer quantidade de caracteres de espaço entre construções sintáticas (inclusive no início e no fim de uma consulta).
  • Os caracteres de espaço incluem espaço, tabulação, quebra de linha, CR e avanço de página.

Comentários

O ClickHouse oferece suporte a comentários no estilo SQL e no estilo C:

  • Comentários no estilo SQL começam com --, #! ou # e vão até o fim da linha. O espaço após -- e #! pode ser omitido.
  • Comentários no estilo C:
    • // (ou mais de 2 caracteres /) seguido de texto até o fim da linha. Não é necessário espaço após /.
    • Podem ir de /* a */ para comentários de várias linhas. Também não é necessário espaço.
    • Comentários no estilo C podem ser aninhados.

Por exemplo:

/*
 * Calcula o número de dias entre duas datas.
 * /* Retorna NULL se algum dos argumentos for NULL */
 */
SELECT
    dateDiff('day', toDate('2024-01-01'), toDate('2024-12-31')) AS days_in_year, -- 365
    dateDiff('day', toDate('2020-01-01'), today()) AS days_since  #! desde 2020
    ///////////////////////////////////////////////////////////////////
    # TODO: adicionar variantes de hora/minuto

Palavras-chave

As palavras-chave no ClickHouse podem ser sensíveis a maiúsculas e minúsculas ou não sensíveis a maiúsculas e minúsculas, dependendo do contexto.

As palavras-chave não diferenciam maiúsculas de minúsculas quando correspondem a:

  • ao padrão SQL. Por exemplo, SELECT, select e SeLeCt são todos válidos.
  • à implementação de alguns SGBDs populares (MySQL ou Postgres). Por exemplo, DateTime é o mesmo que datetime.

Ao contrário do SQL padrão, todas as outras palavras-chave (incluindo nomes de funções) são sensíveis a maiúsculas e minúsculas.

Além disso, as palavras-chave não são reservadas. Elas só são tratadas como tal no contexto correspondente. Se você usar identificadores com o mesmo nome das palavras-chave, coloque-os entre aspas duplas ou backticks.

Por exemplo, a consulta a seguir é válida se a tabela table_name tiver uma coluna com o nome "FROM":

SELECT "FROM" FROM table_name

Identificadores

Os identificadores são:

Os identificadores podem ser colocados entre aspas ou não, embora a segunda opção seja preferível.

Identificadores sem aspas devem corresponder à regex ^[a-zA-Z_][0-9a-zA-Z_]*$ e não podem ser iguais a palavras-chave. Veja a tabela abaixo com exemplos de identificadores válidos e inválidos:

Identificadores válidos Identificadores inválidos
xyz, _internal, Id_with_underscores_123_ 1x, tom@gmail.com, äußerst_schön

Se você quiser usar identificadores iguais a palavras-chave ou usar outros símbolos em identificadores, coloque-os entre aspas duplas ou backticks, por exemplo, "id", `id`.

Literais

No ClickHouse, um literal é um valor representado diretamente em uma consulta. Em outras palavras, é um valor fixo que não se altera durante a execução da consulta.

Os literais podem ser:

A seguir, examinamos cada um deles em mais detalhes nas seções abaixo.

String

Literais de string devem estar entre aspas simples. Aspas duplas não são aceitas.

O escape funciona de uma destas formas:

  • usando uma aspa simples antes, em que o caractere de aspas simples ' (e somente esse caractere) pode ser escapado como '', ou
  • usando uma barra invertida antes, com as seguintes sequências de escape compatíveis listadas na tabela abaixo.
Escape compatível Descrição
\xHH Especificação de caractere de 8 bits seguida por qualquer quantidade de dígitos hexadecimais (H).
\N reservado, não faz nada (por exemplo, SELECT 'a\Nb' retorna ab)
\a alerta
\b retrocesso
\e caractere de escape
\f avanço de página
\n quebra de linha
\r retorno de carro
\t tabulação horizontal
\v tabulação vertical
\0 caractere nulo
\\ barra invertida
\' (ou '') aspas simples
\" aspas duplas
` acento grave
\/ barra normal
\= sinal de igual
Caracteres de controle ASCII (c <= 31).

Numérico

Os literais numéricos são analisados da seguinte forma:

  • Se o literal for precedido por um sinal de menos -, o token será ignorado e o resultado será negado após a análise.
  • O literal numérico é analisado primeiro como um inteiro sem sinal de 64 bits, usando a função strtoull.
    • Se o valor tiver o prefixo 0b ou 0x/0X, o número será analisado como binário ou hexadecimal, respectivamente.
    • Se o valor for negativo e sua magnitude absoluta for maior que 263, um erro será retornado.
  • Se isso não funcionar, o valor será então analisado como um número de ponto flutuante usando a função strtod.
  • Caso contrário, um erro será retornado.

Os valores literais são convertidos para o menor tipo no qual o valor cabe. Por exemplo:

  • 1 é analisado como UInt8
  • 256 é analisado como UInt16.

Para mais informações, consulte Tipos de dados.

Os sublinhados _ dentro de literais numéricos são ignorados e podem ser usados para melhorar a legibilidade.

Há suporte aos seguintes literais numéricos:

Literal numérico Exemplos
Inteiros 1, 10_000_000, 18446744073709551615, 01
Decimais 0.1
Notação exponencial 1e100, -1e-100
Números de ponto flutuante 123.456, inf, nan
Hexadecimal 0xc0fe
String hexadecimal compatível com SQL Standard x'c0fe'
Binário 0b1101
String binária compatível com SQL Standard b'1101'

Compostos

Arrays são construídos com []: [1, 2, 3]. Tuplas são construídas com (): (1, 'Hello, world!', 2). Tecnicamente, eles não são literais, mas expressões com o operador de criação de array e o operador de criação de tupla, respectivamente. Um array deve consistir em pelo menos um item, e uma tupla deve ter pelo menos dois itens.

NULL

NULL é usado para indicar que um valor está ausente. Para armazenar NULL em um campo de uma tabela, ele deve ser do tipo Nullable.

Heredoc

Um heredoc é uma forma de definir uma string (geralmente em várias linhas), mantendo a formatação original. Um heredoc é definido como um literal de string personalizado, colocado entre dois símbolos $.

Por exemplo:

SELECT $heredoc$SHOW CREATE VIEW my_view$heredoc$;

Definição e uso de parâmetros de consulta

Os parâmetros de consulta permitem escrever consultas genéricas que contêm placeholders abstratos em vez de identificadores concretos. Quando uma consulta com parâmetros é executada, todos os placeholders são resolvidos e substituídos pelos valores reais dos parâmetros de consulta.

Os parâmetros de consulta podem ser definidos de várias formas:

  • SET param_<name>=<value> — usando um comando SET em uma consulta.
  • --param_<name>='<value>' — como argumento para o clickhouse-client na linha de comando.
  • param_<name>=<value> — como parâmetro de consulta na URL da interface HTTP.

Um parâmetro de consulta pode ser referenciado em uma consulta usando {<name>: <datatype>}, em que <name> é o nome do parâmetro de consulta e <datatype> é o tipo de dado para o qual ele será convertido.

Exemplo com o comando SET

Por exemplo, o SQL a seguir define parâmetros chamados a, b, c e d — cada um com um tipo de dado diferente:

SET param_a = 13;
SET param_b = 'str';
SET param_c = '2022-08-04 18:30:53';
SET param_d = {'10': [11, 12], '13': [14, 15]};

SELECT
   {a: UInt32},
   {b: String},
   {c: DateTime},
   {d: Map(String, Array(UInt8))};

13    str    2022-08-04 18:30:53    {'10':[11,12],'13':[14,15]}
Exemplo com clickhouse-client

Se você estiver usando o clickhouse-client, os parâmetros serão especificados como --param_name=value. Por exemplo, o parâmetro a seguir tem o nome message e é recuperado como String:

clickhouse-client --param_message='hello' --query="SELECT {message: String}"

hello

Se o parâmetro de consulta representar o nome de um banco de dados, tabela, função ou outro identificador, use Identifier como tipo. Por exemplo, a consulta a seguir retorna linhas de uma tabela chamada uk_price_paid:

SET param_mytablename = "uk_price_paid";
SELECT * FROM {mytablename:Identifier};
Exemplo com a interface HTTP

Os parâmetros de consulta podem ser passados como parâmetros de consulta na URL com o prefixo param_. Por exemplo:

curl -s "http://localhost:8123/?param_message=hello" --data-binary "SELECT {message: String}"

hello
Exemplo com a interface web

A interface web integrada (play.html) detecta automaticamente placeholders de parâmetro no formato {name:Type} na consulta e exibe campos de entrada identificados para cada parâmetro. Os valores dos parâmetros são incluídos na solicitação HTTP e também persistidos na URL da página para permitir favoritos e compartilhamento.

Funções

Chamadas de função são escritas como um identificador seguido de uma lista de argumentos (possivelmente vazia) entre (). Ao contrário do SQL padrão, os parênteses são obrigatórios, mesmo para uma lista de argumentos vazia. Por exemplo:

now()

Há também:

Algumas funções de agregação podem conter duas listas de argumentos entre parênteses. Por exemplo:

quantile (0.9)(x) 

Essas funções de agregação são chamadas de funções "paramétricas", e os argumentos da primeira lista são chamados de "parâmetros".

Operadores

Os operadores são convertidos nas funções correspondentes durante a análise sintática da consulta, levando em conta sua prioridade e associatividade.

Por exemplo, a expressão

1 + 2 * 3 + 4

é convertido em

plus(plus(1, multiply(2, 3)), 4)`

Tipos de dados e motores de tabela do banco de dados

Os tipos de dados e os motores de tabela na consulta CREATE são escritos da mesma forma que identificadores ou funções. Em outras palavras, eles podem ou não conter uma lista de argumentos entre parênteses.

Para mais informações, consulte as seções:

Expressões

Uma expressão pode ser qualquer um dos itens a seguir:

  • uma função
  • um identificador
  • um literal
  • a aplicação de um operador
  • uma expressão entre parênteses
  • uma subconsulta
  • um asterisco

Ela também pode conter um alias.

Uma lista de expressões consiste em uma ou mais expressões separadas por vírgulas. Funções e operadores, por sua vez, podem ter expressões como argumentos.

Uma expressão constante é uma expressão cujo resultado é conhecido durante a análise da consulta, isto é, antes da execução. Por exemplo, expressões com literais são expressões constantes.

Aliases de expressão

Um alias é um nome atribuído pelo usuário a uma expressão em uma consulta.

expr AS alias

As partes da sintaxe acima são explicadas abaixo.

Parte da sintaxe Descrição Exemplo Observações
AS A palavra-chave usada para definir aliases. Você pode definir o alias de um nome de tabela ou de uma coluna em uma cláusula SELECT sem usar a palavra-chave AS. SELECT table_name_alias.column_name FROM table_name table_name_alias. Na função CAST, a palavra-chave AS tem outro significado. Consulte a descrição da função.
expr Qualquer expressão suportada pelo ClickHouse. SELECT column_name * 2 AS double FROM some_table
alias Nome de expr. Os aliases devem seguir a sintaxe de identificadores. SELECT "table t".column_name FROM table_name AS "table t".

Notas de uso

  • Aliases são globais em uma consulta ou subconsulta, e você pode definir um alias em qualquer parte da consulta para qualquer expressão. Por exemplo:
SELECT (1 AS n) + 2, n`.
  • Aliases não ficam visíveis em subconsultas nem entre subconsultas. Por exemplo, ao executar a consulta a seguir, ClickHouse gera a exceção Unknown identifier: num:
`SELECT (SELECT sum(b.a) + num FROM b) - a.a AS num FROM a`
  • Se um alias for definido para as colunas de resultado na cláusula SELECT de uma subconsulta, essas colunas ficam visíveis na consulta externa. Por exemplo:
SELECT n + m FROM (SELECT 1 AS n, 2 AS m)`.
  • Tenha cuidado com aliases que sejam iguais a nomes de colunas ou tabelas. Vamos considerar o exemplo a seguir:
CREATE TABLE t
(
    a Int,
    b Int
)
ENGINE = TinyLog();

SELECT
    argMax(a, b),
    sum(b) AS b
FROM t;

Received exception from server (version 18.14.17):
Code: 184. DB::Exception: Received from localhost:9000, 127.0.0.1. DB::Exception: Aggregate function sum(b) is found inside another aggregate function in query.

No exemplo anterior, declaramos a tabela t com a coluna b. Em seguida, ao selecionar os dados, definimos o alias sum(b) AS b. Como os aliases têm escopo global, ClickHouse substituiu o literal b na expressão argMax(a, b) pela expressão sum(b). Essa substituição causou a exceção.

Asterisco

Em uma consulta SELECT, um asterisco pode substituir a expressão. Para mais informações, consulte a seção SELECT.

Navigation