> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-3a82795f.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Inserção avançada com ClickHouse Connect

# Inserção avançada

<div id="inserting-data-with-clickhouse-connect--advanced-usage">
  ## Inserção de dados com ClickHouse Connect: uso avançado
</div>

<div id="insertcontexts">
  ### InsertContexts
</div>

O ClickHouse Connect executa todas as inserções em um `InsertContext`. O `InsertContext` inclui todos os valores enviados como argumentos para o método `insert` do cliente. Além disso, quando um `InsertContext` é criado pela primeira vez, o ClickHouse Connect recupera os tipos de dados das colunas de inserção necessários para inserções eficientes no formato Native. Ao reutilizar o `InsertContext` em várias inserções, essa "pré-consulta" é evitada, e as inserções são executadas com mais rapidez e eficiência.

Um `InsertContext` pode ser obtido usando o método `create_insert_context` do cliente. O método recebe os mesmos argumentos que a função `insert`. Observe que, para reutilização, apenas a propriedade `data` dos `InsertContext`s deve ser modificada. Isso está de acordo com seu propósito de fornecer um objeto reutilizável para inserções repetidas de novos dados na mesma tabela.

```python theme={null}
test_data = [[1, 'v1', 'v2'], [2, 'v3', 'v4']]
ic = test_client.create_insert_context(table='test_table', data='test_data')
client.insert(context=ic)
assert client.command('SELECT count() FROM test_table') == 2
new_data = [[3, 'v5', 'v6'], [4, 'v7', 'v8']]
ic.data = new_data
client.insert(context=ic)
qr = test_client.query('SELECT * FROM test_table ORDER BY key DESC')
assert qr.row_count == 4
assert qr[0][0] == 4
```

`InsertContext`s incluem estado mutável que é atualizado durante o processo de insert, portanto não são thread-safe.

<div id="write-formats">
  ### Formatos de escrita
</div>

Atualmente, os formatos de escrita estão implementados para um número limitado de tipos. Na maioria dos casos, o ClickHouse Connect tentará determinar automaticamente o formato de escrita correto de uma coluna verificando o tipo do primeiro valor de dados não nulo. Por exemplo, ao inserir em uma coluna `DateTime`, se o primeiro valor inserido na coluna for um inteiro do Python, o ClickHouse Connect inserirá esse valor diretamente, partindo do pressuposto de que ele representa um segundo epoch.

Na maioria dos casos, não é necessário substituir o formato de escrita de um tipo de dado, mas os métodos correspondentes no pacote `clickhouse_connect.datatypes.format` podem ser usados para fazer isso em nível global.

<div id="write-format-options">
  #### Opções de formato de escrita
</div>

| ClickHouse Type         | Tipo nativo do Python   | Formatos de escrita | Comentários                                                                                                                          |
| ----------------------- | ----------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Int\[8-64], UInt\[8-32] | int                     | -                   |                                                                                                                                      |
| UInt64                  | int                     |                     |                                                                                                                                      |
| \[U]Int\[128,256]       | int                     |                     |                                                                                                                                      |
| BFloat16                | float                   |                     |                                                                                                                                      |
| Float32                 | float                   |                     |                                                                                                                                      |
| Float64                 | float                   |                     |                                                                                                                                      |
| Decimal                 | decimal.Decimal         |                     |                                                                                                                                      |
| String                  | string                  |                     |                                                                                                                                      |
| FixedString             | bytes                   | string              | Se inserido como string, os bytes adicionais serão preenchidos com zeros                                                             |
| Enum\[8,16]             | string                  |                     |                                                                                                                                      |
| Date                    | datetime.date           | int                 | O ClickHouse armazena valores Date como o número de dias desde 01/01/1970. Tipos `int` serão considerados esse valor de "data epoch" |
| Date32                  | datetime.date           | int                 | Igual a Date, mas para um intervalo maior de datas                                                                                   |
| DateTime                | datetime.datetime       | int                 | O ClickHouse armazena DateTime em segundos epoch. Tipos `int` serão considerados esse valor de "segundo epoch"                       |
| DateTime64              | datetime.datetime       | int                 | O `datetime.datetime` do Python é limitado à precisão de microssegundos. O valor bruto de `int` de 64 bits está disponível           |
| Time                    | datetime.timedelta      | int, string, time   | O ClickHouse armazena DateTime em segundos epoch. Tipos `int` serão considerados esse valor de "segundo epoch"                       |
| Time64                  | datetime.timedelta      | int, string, time   | O `datetime.timedelta` do Python é limitado à precisão de microssegundos. O valor bruto de `int` de 64 bits está disponível          |
| IPv4                    | `ipaddress.IPv4Address` | string              | Strings formatadas corretamente podem ser inseridas como endereços IPv4                                                              |
| IPv6                    | `ipaddress.IPv6Address` | string              | Strings formatadas corretamente podem ser inseridas como endereços IPv6                                                              |
| Tuple                   | dict or tuple           |                     |                                                                                                                                      |
| Map                     | dict                    |                     |                                                                                                                                      |
| Nested                  | Sequence\[dict]         |                     |                                                                                                                                      |
| UUID                    | uuid.UUID               | string              | Strings formatadas corretamente podem ser inseridas como UUIDs do ClickHouse                                                         |
| JSON/Object('json')     | dict                    | string              | Tanto dicionários quanto strings JSON podem ser inseridos em colunas JSON (observe que `Object('json')` está obsoleto)               |
| Variant                 | object                  |                     | No momento, todos os valores Variant são inseridos como Strings e analisados pelo servidor ClickHouse                                |
| Dynamic                 | object                  |                     | Aviso -- no momento, quaisquer inserções em uma coluna Dynamic são persistidas como String do ClickHouse                             |

<div id="specialized-insert-methods">
  ### Métodos de inserção especializados
</div>

O ClickHouse Connect fornece métodos de inserção especializados para formatos de dados comuns:

* `insert_df` -- Insere um DataFrame do Pandas. Em vez de usar o argumento `data` como uma Sequence of Sequences do Python, o segundo parâmetro desse método exige um argumento `df`, que deve ser uma instância de DataFrame do Pandas. O ClickHouse Connect processa automaticamente o DataFrame como uma fonte de dados orientada por colunas, portanto o parâmetro `column_oriented` não é necessário nem está disponível.
* `insert_arrow` -- Insere uma tabela PyArrow. O ClickHouse Connect passa a tabela Arrow sem modificações para o servidor ClickHouse para processamento, portanto, além de `table` e `arrow_table`, apenas os argumentos `database` e `settings` estão disponíveis.
* `insert_df_arrow` -- Insere um DataFrame do Pandas com Arrow como backend ou um DataFrame do Polars. O ClickHouse Connect determinará automaticamente se o DataFrame é do tipo Pandas ou Polars. Se for Pandas, será feita uma validação para garantir que o backend `dtype` de cada coluna seja baseado em Arrow, e um erro será gerado se alguma não for.

<Note>
  Um array do NumPy é uma Sequence of Sequences válida e pode ser usado como argumento `data` no método principal `insert`, portanto não é necessário um método especializado.
</Note>

<div id="pandas-dataframe-insert">
  #### Inserção de DataFrame do Pandas
</div>

```python theme={null}
import clickhouse_connect
import pandas as pd

client = clickhouse_connect.get_client()

df = pd.DataFrame({
    "id": [1, 2, 3],
    "name": ["Alice", "Bob", "Joe"],
    "age": [25, 30, 28],
})

client.insert_df("users", df)
```

<div id="pyarrow-table-insert">
  #### Inserção de tabela PyArrow
</div>

```python theme={null}
import clickhouse_connect
import pyarrow as pa

client = clickhouse_connect.get_client()

arrow_table = pa.table({
    "id": [1, 2, 3],
    "name": ["Alice", "Bob", "Joe"],
    "age": [25, 30, 28],
})

client.insert_arrow("users", arrow_table)
```

<div id="arrow-backed-dataframe-insert-pandas-2">
  #### Inserção de DataFrame com Arrow como backend (pandas 2.x)
</div>

```python theme={null}
import clickhouse_connect
import pandas as pd

client = clickhouse_connect.get_client()

# Converte para dtypes com suporte a Arrow para melhor desempenho
df = pd.DataFrame({
    "id": [1, 2, 3],
    "name": ["Alice", "Bob", "Joe"],
    "age": [25, 30, 28],
}).convert_dtypes(dtype_backend="pyarrow")

client.insert_df_arrow("users", df)
```

<div id="time-zones">
  ### Fusos horários
</div>

Ao inserir objetos `datetime.datetime` do Python em colunas `DateTime` ou `DateTime64` do ClickHouse, o ClickHouse Connect trata automaticamente as informações de fuso horário. Como o ClickHouse armazena internamente todos os valores `DateTime` como timestamps Unix sem fuso horário (segundos ou frações de segundo desde a epoch), a conversão de fuso horário ocorre automaticamente no lado do cliente durante a inserção.

<div id="timezone-aware-datetime-objects">
  #### Objetos datetime com fuso horário
</div>

Se você inserir um objeto `datetime.datetime` do Python com fuso horário, o ClickHouse Connect chamará automaticamente `.timestamp()` para convertê-lo em um Unix timestamp, o que leva corretamente em conta o deslocamento do fuso horário. Isso significa que você pode inserir objetos datetime de qualquer fuso horário, e eles serão armazenados corretamente como o timestamp equivalente em UTC.

```python theme={null}
import clickhouse_connect
from datetime import datetime
import pytz

client = clickhouse_connect.get_client()
client.command("CREATE TABLE events (event_time DateTime) ENGINE Memory")

# Inserir objetos datetime com fuso horário
denver_tz = pytz.timezone('America/Denver')
tokyo_tz = pytz.timezone('Asia/Tokyo')

data = [
    [datetime(2023, 6, 15, 10, 30, 0, tzinfo=pytz.UTC)],
    [denver_tz.localize(datetime(2023, 6, 15, 10, 30, 0))],
    [tokyo_tz.localize(datetime(2023, 6, 15, 10, 30, 0))]
]

client.insert('events', data, column_names=['event_time'])
results = client.query("SELECT * from events")
print(*results.result_rows, sep="\n")
# Saída:
# (datetime.datetime(2023, 6, 15, 10, 30),)
# (datetime.datetime(2023, 6, 15, 16, 30),)
# (datetime.datetime(2023, 6, 15, 1, 30),)
```

Neste exemplo, os três objetos datetime representam instantes diferentes, porque têm fusos horários diferentes. Cada um será convertido corretamente para o respectivo Unix timestamp e armazenado no ClickHouse.

<Note>
  Ao usar pytz, você deve usar o método `localize()` para adicionar informações de fuso horário a um datetime ingênuo. Passar `tzinfo=` diretamente para o construtor de datetime usará deslocamentos históricos incorretos. Para UTC, `tzinfo=pytz.UTC` funciona corretamente. Consulte a [documentação do pytz](https://pythonhosted.org/pytz/#localized-times-and-date-arithmetic) para mais informações.
</Note>

<div id="timezone-naive-datetime-objects">
  #### Objetos datetime sem informação de fuso horário
</div>

Se você inserir um objeto `datetime.datetime` do Python sem informação de fuso horário (ou seja, sem `tzinfo`), o método `.timestamp()` o interpretará como se estivesse no fuso horário local do sistema. Para evitar ambiguidades, recomenda-se:

1. Sempre usar objetos `datetime` com fuso horário ao inserir, ou
2. Garantir que o fuso horário do sistema esteja definido como UTC, ou
3. Converter manualmente para timestamps epoch antes de inserir

```python theme={null}
import clickhouse_connect
from datetime import datetime
import pytz

client = clickhouse_connect.get_client()

# Recomendado: sempre use datetimes com fuso horário definido
utc_time = datetime(2023, 6, 15, 10, 30, 0, tzinfo=pytz.UTC)
client.insert('events', [[utc_time]], column_names=['event_time'])

# Alternativa: converter para epoch timestamp manualmente
naive_time = datetime(2023, 6, 15, 10, 30, 0)
epoch_timestamp = int(naive_time.replace(tzinfo=pytz.UTC).timestamp())
client.insert('events', [[epoch_timestamp]], column_names=['event_time'])
```

<div id="datetime-columns-with-timezone-metadata">
  #### Colunas DateTime com metadados de fuso horário
</div>

As colunas do ClickHouse podem ser definidas com metadados de fuso horário (por exemplo, `DateTime('America/Denver')` ou `DateTime64(3, 'Asia/Tokyo')`). Esses metadados não afetam a forma como os dados são armazenados (ainda como timestamps UTC), mas controlam o fuso horário usado ao consultar os dados no ClickHouse.

Ao inserir dados nessas colunas, o ClickHouse Connect converte seu datetime do Python em um Unix timestamp (considerando o fuso horário, se houver). Ao consultar os dados novamente, o ClickHouse Connect retorna o datetime convertido para o fuso horário da coluna, independentemente do fuso horário usado na inserção.

```python theme={null}
import clickhouse_connect
from datetime import datetime
import pytz

client = clickhouse_connect.get_client()

# Cria tabela com metadados de fuso horário de Los Angeles
client.command("CREATE TABLE events (event_time DateTime('America/Los_Angeles')) ENGINE Memory")

# Insere um horário de Nova York (10:30 AM EDT, que é 14:30 UTC)
ny_tz = pytz.timezone("America/New_York")
data = ny_tz.localize(datetime(2023, 6, 15, 10, 30, 0))
client.insert("events", [[data]], column_names=["event_time"])

# Ao consultar, o horário é automaticamente convertido para o fuso horário de Los Angeles
# 10:30 AM Nova York (UTC-4) = 14:30 UTC = 7:30 AM Los Angeles (UTC-7)
results = client.query("select * from events")
print(*results.result_rows, sep="\n")
# Saída:
# (datetime.datetime(2023, 6, 15, 7, 30, tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>),)
```

<div id="file-inserts">
  ## Inserções de arquivos
</div>

O pacote `clickhouse_connect.driver.tools` inclui o método `insert_file`, que permite inserir dados diretamente do sistema de arquivos em uma tabela existente do ClickHouse. O parsing é delegado ao servidor ClickHouse. `insert_file` aceita os seguintes parâmetros:

| Parâmetro     | Tipo            | Padrão            | Descrição                                                                                                                                            |
| ------------- | --------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| client        | Client          | *Obrigatório*     | O `driver.Client` usado para realizar a inserção                                                                                                     |
| table         | str             | *Obrigatório*     | A tabela do ClickHouse na qual os dados serão inseridos. O nome completo da tabela (incluindo o banco de dados) é permitido.                         |
| file\_path    | str             | *Obrigatório*     | O caminho nativo no sistema de arquivos para o arquivo de dados                                                                                      |
| fmt           | str             | CSV, CSVWithNames | O formato de entrada do ClickHouse do arquivo. CSVWithNames é assumido se `column_names` não for fornecido                                           |
| column\_names | Sequence of str | *None*            | Uma lista de nomes de colunas no arquivo de dados. Não é necessária para formatos que incluem nomes de colunas                                       |
| database      | str             | *None*            | Banco de dados da tabela. Ignorado se a tabela estiver totalmente qualificada. Se não for especificado, a inserção usará o banco de dados do cliente |
| settings      | dict            | *None*            | Veja a [descrição das configurações](/pt-BR/integrations/language-clients/python/driver-api#settings-argument).                                      |
| compression   | str             | *None*            | Um tipo de compressão do ClickHouse reconhecido (zstd, lz4, gzip) usado no cabeçalho HTTP `Content-Encoding`                                         |

Para arquivos com dados inconsistentes ou valores de data/hora em um formato incomum, este método reconhece configurações aplicáveis a importações de dados (como `input_format_allow_errors_num` e `input_format_allow_errors_num`).

```python theme={null}
import clickhouse_connect
from clickhouse_connect.driver.tools import insert_file

client = clickhouse_connect.get_client()
insert_file(client, 'example_table', 'my_data.csv',
            settings={'input_format_allow_errors_ratio': .2,
                      'input_format_allow_errors_num': 5})
```
