> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> Permite executar consultas SELECT e INSERT em uma tabela do Google BigQuery, incluindo conjuntos de dados públicos.

# bigquery

Permite executar consultas `SELECT` e `INSERT` em uma tabela no [Google BigQuery](https://cloud.google.com/bigquery), incluindo conjuntos de dados públicos. A estrutura da tabela é inferida automaticamente do esquema da tabela do BigQuery.

A leitura usa a API REST do BigQuery (`tabledata.list`); portanto, apenas tabelas nativas podem ser lidas (não é possível ler visões, visões materializadas nem tabelas externas). A gravação usa inserções por streaming (`tabledata.insertAll`), o que exige que o faturamento esteja habilitado para o projeto.

<div id="syntax">
  ## Sintaxe
</div>

```sql theme={null}
bigquery(project, dataset, table[, access_token][, key = value, ...])
bigquery(named_collection[, key = value, ...])
```

<div id="arguments">
  ## Argumentos
</div>

| Argumento      | Descrição                                                                                                                                                                |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `project`      | O projeto do Google Cloud ao qual o conjunto de dados pertence. Para conjuntos de dados públicos, é o projeto do conjunto de dados, por exemplo, `bigquery-public-data`. |
| `dataset`      | O nome do conjunto de dados.                                                                                                                                             |
| `table`        | O nome da tabela.                                                                                                                                                        |
| `access_token` | Um token de acesso OAuth 2.0 (argumento posicional opcional; consulte [Autenticação](#authentication)).                                                                  |

Os argumentos `project`, `dataset`, `table` e `access_token` também podem ser fornecidos no formato `key = value`; os argumentos posicionais preenchem essas posições nessa ordem, e especificar um argumento tanto por posição quanto como chave (ou repetir a mesma chave) gera um erro.

Os seguintes argumentos podem ser especificados no formato `key = value` (ou como chaves de uma coleção nomeada):

| Chave                 | Descrição                                                                                                                                                          |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `access_token`        | Um token de acesso OAuth 2.0.                                                                                                                                      |
| `service_account_key` | O conteúdo de um arquivo JSON de chave de conta de serviço do Google.                                                                                              |
| `client_id`           | ID do cliente OAuth 2.0 (usado com `client_secret` e `refresh_token`).                                                                                             |
| `client_secret`       | Segredo do cliente OAuth 2.0.                                                                                                                                      |
| `refresh_token`       | Token de atualização OAuth 2.0.                                                                                                                                    |
| `billing_project`     | Projeto opcional ao qual atribuir a cota e o faturamento (enviado no cabeçalho `X-Goog-User-Project`).                                                             |
| `base_url`            | O endpoint da API, `https://bigquery.googleapis.com` por padrão. Pode ser alterado para testes e emuladores.                                                       |
| `token_url`           | Substituição do endpoint de token OAuth para testes e emuladores. Por padrão, o `token_uri` da chave da conta de serviço ou `https://oauth2.googleapis.com/token`. |

<div id="authentication">
  ## Autenticação
</div>

É necessário fornecer exatamente um método de autenticação. O BigQuery não permite acesso anônimo; portanto, as credenciais são necessárias até mesmo para conjuntos de dados públicos.

1. **Token de acesso**. Qualquer token de acesso OAuth 2.0 válido, por exemplo, obtido com `gcloud auth print-access-token`. Os tokens expiram rapidamente (geralmente após uma hora), portanto, esse método é mais adequado para uso interativo.
2. **Chave de conta de serviço** (recomendada para servidores). Forneça o conteúdo de um arquivo de chave criado no Google Cloud IAM usando o argumento `service_account_key`. O ClickHouse assina um JWT com a chave e o troca por um token de acesso, renovando-o automaticamente.
3. **Token de atualização**. Forneça `client_id`, `client_secret` e `refresh_token`, por exemplo, extraídos de `~/.config/gcloud/application_default_credentials.json` após executar `gcloud auth application-default login`.

Armazene as credenciais em uma [coleção nomeada](/docs/pt-BR/concepts/features/configuration/server-config/named-collections) para evitar especificá-las em cada consulta. Uma tabela permanente criada a partir de uma coleção nomeada (com o motor de tabela `BigQuery` ou `CREATE TABLE ... AS bigquery(...)`) é registrada como dependência da coleção. Portanto, `DROP NAMED COLLECTION` é bloqueado enquanto a tabela existir.

<div id="data-type-mapping">
  ## Mapeamento de tipos de dados
</div>

| Tipo do BigQuery      | Tipo do ClickHouse                                                                                                                                                                                     |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `STRING`              | [String](/docs/pt-BR/reference/data-types/string)                                                                                                                                                           |
| `BYTES`               | [String](/docs/pt-BR/reference/data-types/string) (bytes brutos)                                                                                                                                            |
| `INTEGER` / `INT64`   | [Int64](/docs/pt-BR/reference/data-types/int-uint)                                                                                                                                                          |
| `FLOAT` / `FLOAT64`   | [Float64](/docs/pt-BR/reference/data-types/float)                                                                                                                                                           |
| `BOOLEAN` / `BOOL`    | [Bool](/docs/pt-BR/reference/data-types/boolean)                                                                                                                                                            |
| `TIMESTAMP`           | [DateTime64(6, 'UTC')](/docs/pt-BR/reference/data-types/datetime64)                                                                                                                                         |
| `DATE`                | [Date32](/docs/pt-BR/reference/data-types/date32)                                                                                                                                                           |
| `TIME`                | [Time64(6)](/docs/pt-BR/reference/data-types/time64)                                                                                                                                                        |
| `DATETIME`            | [DateTime64(6, 'UTC')](/docs/pt-BR/reference/data-types/datetime64)                                                                                                                                         |
| `NUMERIC` / `DECIMAL` | [Decimal(38, 9)](/docs/pt-BR/reference/data-types/decimal), ou `Decimal(P, S)` quando parametrizado                                                                                                         |
| `BIGNUMERIC`          | [Decimal(76, 38)](/docs/pt-BR/reference/data-types/decimal), ou `Decimal(P, S)` quando parametrizado                                                                                                        |
| `GEOGRAPHY`           | [Geometry](/docs/pt-BR/reference/data-types/geo#geometry) (convertido de WKT)                                                                                                                               |
| `JSON`                | [String](/docs/pt-BR/reference/data-types/string)                                                                                                                                                           |
| `INTERVAL`            | [String](/docs/pt-BR/reference/data-types/string)                                                                                                                                                           |
| `RANGE`               | [String](/docs/pt-BR/reference/data-types/string) (somente leitura)                                                                                                                                         |
| `RECORD` / `STRUCT`   | [Tuple](/docs/pt-BR/reference/data-types/tuple), ou [Nullable](/docs/pt-BR/reference/data-types/nullable)(`Tuple`) no modo `NULLABLE`                                                                            |
| Modo `REPEATED`       | [Array](/docs/pt-BR/reference/data-types/array) do tipo de elemento, com elementos não `Nullable` (`Array(Tuple(...))` para elementos `RECORD`), pois um array do BigQuery não pode conter elementos `NULL` |
| Modo `NULLABLE`       | [Nullable](/docs/pt-BR/reference/data-types/nullable) (exceto `GEOGRAPHY`, cujo tipo `Geometry` aceita `NULL` diretamente)                                                                                  |

Notas:

* O `DATETIME` do BigQuery não tem fuso horário; ele é mapeado para `DateTime64(6, 'UTC')` para que o valor exibido não dependa do fuso horário do servidor.
* Um `RECORD` `NULLABLE` é mapeado para `Nullable(Tuple(...))`, preservando um `NULL` de registro completo como `NULL`, em vez de reduzi-lo a um `Tuple` de valores padrão. Um array `NULL` (ou vazio) se torna um array vazio, pois `Array` não pode estar dentro de `Nullable` no ClickHouse. Um array do BigQuery não pode conter elementos `NULL` (`ARRAY<T>` é equivalente a `ARRAY<T NOT NULL>`); portanto, o tipo de elemento de um campo `REPEATED` não é `Nullable` (`Array(T)` ou `Array(Tuple(...))` para um elemento `RECORD`). Um elemento `NULL` em uma resposta `tabledata.list` é rejeitado como entrada malformada.
* A leitura e a gravação de colunas `Nullable(Tuple(...))` por meio da função de tabela `bigquery` funcionam sem configurações adicionais. A criação de uma tabela persistente com o mecanismo `BigQuery` que contenha essa coluna, seja com a estrutura inferida ou declarada explicitamente, requer a configuração `enable_nullable_tuple_type`, assim como qualquer coluna `Nullable(Tuple)`. Ao declarar colunas explicitamente, um campo `RECORD` pode ser declarado como um `Tuple(...)` simples para evitar essa configuração, ao custo de converter um `NULL` de registro completo em uma tupla padrão; a única diferença aceita em relação ao tipo inferido é remover o `Nullable` que envolve o `Tuple` de um `RECORD`, e somente nesse mesmo registro — a nulabilidade não pode ser movida para outro registro, interno ou externo.
* `GEOGRAPHY` é mapeado para [Geometry](/docs/pt-BR/reference/data-types/geo#geometry). O BigQuery transfere um valor `GEOGRAPHY` como texto [WKT](https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry), que é analisado como a alternativa correspondente de `Geometry` (um `Variant` de `Point`, `MultiPoint`, `Ring`, `LineString`, `MultiLineString`, `Polygon` e `MultiPolygon`) na leitura e serializado novamente como WKT na gravação. Uma `GEOMETRYCOLLECTION` e uma geometria vazia, como `POINT EMPTY`, não têm equivalente em `Geometry`; portanto, a leitura de uma linha que contenha esse valor gera um erro. Como `Variant` já comporta um `NULL`, um campo `GEOGRAPHY` `NULLABLE` é mapeado para `Geometry`, e não para `Nullable(Geometry)`, e o `NULL` continua sendo preservado na ida e volta.
* `JSON` é mapeado para `String`, em vez do tipo de dados [JSON](/docs/pt-BR/reference/data-types/newjson), porque o tipo `JSON` do ClickHouse aceita apenas um objeto (`{...}`) no nível superior, enquanto um valor `JSON` do BigQuery pode ser qualquer valor JSON — um escalar, um array ou `null`. Portanto, uma tabela que contenha esses valores não poderia ser lida. Além disso, `JSON` não pode ser envolvido em `Nullable`, de modo que um `NULL` SQL em uma coluna `NULLABLE` não seria preservado. O mapeamento para `String` não perde dados; objetos de nível superior podem ser convertidos com `CAST(value AS JSON)`.
* Valores `BIGNUMERIC` com mais de 38 dígitos na parte inteira não cabem em `Decimal(76, 38)` e geram um erro.
* Valores `TIMESTAMP` e `DATE` fora do intervalo de `DateTime64`/`Date32` (anos de 1900 a 2299) não são compatíveis.
* Colunas `RANGE` são somente leitura. `tabledata.insertAll` espera um valor `RANGE<T>` como um objeto estruturado `{start, end}`, que não pode ser reconstruído a partir do mapeamento para `String`; portanto, a inserção em uma coluna `RANGE` gera um erro.
* Valores `INT64` são enviados para `tabledata.insertAll` como strings decimais, pois a API interpreta números JSON como doubles e, caso contrário, corromperia valores fora de `[-2^53 + 1, 2^53 - 1]`.

<div id="examples">
  ## Exemplos
</div>

Leia um conjunto de dados público usando um token do `gcloud`:

```sql theme={null}
SELECT word, sum(word_count) AS c
FROM bigquery('bigquery-public-data', 'samples', 'shakespeare', '<access token>')
GROUP BY word
ORDER BY c DESC
LIMIT 5;
```

Leia uma tabela privada usando um arquivo de chave de conta de serviço:

```sql theme={null}
SELECT count()
FROM bigquery('my-project', 'my_dataset', 'my_table',
              service_account_key = '{"type": "service_account", "private_key": "...", "client_email": "...", ...}');
```

Inserir dados (inserção em streaming, requer faturamento habilitado):

```sql theme={null}
INSERT INTO FUNCTION bigquery('my-project', 'my_dataset', 'my_table', '<access token>')
SELECT number AS id, toString(number) AS name FROM numbers(10);
```

Use uma coleção nomeada:

```xml theme={null}
<clickhouse>
    <named_collections>
        <my_bigquery>
            <project>my-project</project>
            <dataset>my_dataset</dataset>
            <service_account_key><![CDATA[{"type": "service_account", ...}]]></service_account_key>
        </my_bigquery>
    </named_collections>
</clickhouse>
```

```sql theme={null}
SELECT * FROM bigquery(my_bigquery, table = 'my_table');
```

<div id="limitations">
  ## Limitações
</div>

* Somente tabelas nativas do BigQuery podem ser lidas. Views e tabelas externas exigem a execução de um job de consulta do BigQuery, o que esta função não faz.
* Colunas `RANGE` podem ser lidas (como `String`), mas não gravadas: inserir em uma coluna `RANGE` gera um erro.
* Um valor `GEOGRAPHY` que seja uma `GEOMETRYCOLLECTION` ou uma geometria vazia não pode ser representado pelo tipo `Geometry`; portanto, a leitura de uma linha que contenha um desses valores gera um erro. Gravar um `Geometry` `NULL` em um campo `GEOGRAPHY` `REQUIRED`, ou como elemento de um campo `GEOGRAPHY` `REPEATED`, é rejeitado, pois o BigQuery não aceita `NULL` nesses casos.
* Os predicados não são enviados para baixo: `tabledata.list` apenas lista as linhas de uma tabela e não tem nenhum parâmetro de filtragem (aceita opções de paginação, seleção de colunas e formato), e a filtragem exigiria a execução de um job de consulta do BigQuery, o que esta função não faz. Portanto, uma condição `WHERE` é aplicada no ClickHouse depois que as linhas são baixadas; use a seleção de colunas para reduzir os dados transferidos.
* Por outro lado, um `LIMIT` reduz a quantidade de dados lidos. As páginas são solicitadas sob demanda, com `maxResults` definido como `max_block_size`, e nenhuma página adicional é solicitada quando a consulta já tem linhas suficientes. Para um `LIMIT n` trivial (sem `WHERE`, `GROUP BY`, `ORDER BY` e com `n` menor que `max_block_size`), o ClickHouse reduz `max_block_size` para `n`, de modo que é feita exatamente uma solicitação para exatamente `n` linhas; caso contrário, a leitura é interrompida no primeiro limite de página após o limite, excedendo-o em menos de uma página.
* A leitura fica vinculada ao schema observado no momento da análise da consulta, passando a lista explícita de colunas para `tabledata.list`. Para uma leitura muito ampla cuja lista de colunas excederia o limite de comprimento da URL da solicitação (por exemplo, `SELECT *` de uma tabela com milhares de colunas), a consulta é rejeitada em vez de ser executada sem essa vinculação (uma leitura sem vinculação poderia ser desalinhada por uma alteração concorrente no schema); selecione menos colunas para que a lista caiba. O mesmo limite de comprimento da URL é verificado antes de cada solicitação paginada (cada página inclui um `pageToken` opaco); portanto, uma leitura cujas páginas posteriores não caibam no limite é rejeitada com o mesmo erro, em vez de falhar no meio do processo.
* Se a tabela do BigQuery for alterada depois que seu schema tiver sido lido, a consulta será rejeitada em vez de retornar ou gravar dados incompatíveis silenciosamente: o schema atual é buscado novamente e comparado ao analisado imediatamente antes de uma leitura e novamente antes que um `INSERT` transmita sua primeira linha. A janela restante — uma alteração no schema entre essa verificação e as solicitações subsequentes — não pode ser eliminada, pois o schema e os dados são buscados por solicitações REST separadas.
* A comparação é feita com o snapshot do schema usado na análise da consulta, obtido quando a função de tabela resolve sua estrutura ou, no caso de uma tabela persistente (uma tabela com engine `BigQuery` ou uma tabela criada com `CREATE TABLE ... AS bigquery(...)`, que persiste suas colunas da mesma forma), em sua primeira leitura ou gravação após `CREATE`, `ATTACH` ou uma reinicialização do servidor. Os metadados da tabela persistem as colunas mapeadas do ClickHouse, e não o schema do BigQuery; portanto, uma alteração no schema feita enquanto a tabela estava desanexada (ou o servidor estava inativo) é adotada pela próxima consulta em vez de ser rejeitada: as colunas declaradas ainda são validadas em relação ao schema atual, e as linhas são decodificadas com base nele, de modo que uma alteração que preserve os tipos mapeados do ClickHouse (`STRING` para `BYTES`, por exemplo) seja lida segundo as regras do novo tipo, mantendo o mesmo tipo de coluna.
* As linhas gravadas com inserts de streaming chegam ao buffer de streaming do BigQuery e podem levar algum tempo para se tornarem visíveis em leituras subsequentes.
* Um `INSERT` grande é enviado para `tabledata.insertAll` em batches: no máximo 500 linhas por solicitação, além de ser dividido para que cada solicitação permaneça abaixo do limite de tamanho de 10 MB do BigQuery (uma única linha maior que esse limite é rejeitada com um erro claro).
* As operações de gravação não são atômicas, e uma única solicitação `tabledata.insertAll` pode ser parcialmente bem-sucedida: o BigQuery pode confirmar algumas linhas de uma solicitação e rejeitar outras com `insertErrors`. As solicitações também são confirmadas de forma independente, portanto, um lote posterior pode ser rejeitado depois que lotes anteriores forem aceitos. Em ambos os casos, a consulta relata um erro, mas as linhas já confirmadas permanecem no BigQuery. Para limitar duplicações, cada linha é enviada com um `insertId` estável, derivado do ID da consulta e da posição ordinal da linha no stream, que o BigQuery usa para desduplicação de melhor esforço dentro da janela de inserção por streaming. Um `query_id` que exceda o limite de 128 caracteres do `insertId` do BigQuery é submetido a hash para gerar um prefixo de comprimento fixo, que permanece estável para esse `query_id`. Como o `insertId` depende da posição ordinal, a desduplicação só é confiável quando a reexecução produz as linhas na mesma ordem: uma nova tentativa de um lote no nível de transporte é sempre segura, e reexecutar o mesmo `INSERT` com o mesmo `query_id` só desduplica se as linhas forem apresentadas na mesma ordem (por exemplo, uma inserção de thread única ou uma ordenação determinística — defina `max_threads = 1` e `max_insert_threads = 1` para um `INSERT ... SELECT` paralelo cuja ordem dos fragmentos poderia mudar entre tentativas).

<div id="related">
  ## Relacionados
</div>

* [Motor de tabela `BigQuery`](/docs/pt-BR/reference/engines/table-engines/integrations/bigquery)
