> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-parallel-read-in-order-multi-part.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

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

<h3 id="insertcontexts">
  InsertContexts
</h3>

O ClickHouse Connect executa inserções no formato Native, pelos métodos `insert` e `insert_df`, em um `InsertContext`. Os métodos `insert_arrow`, `insert_df_arrow` e `raw_insert` enviam seus payloads diretamente e não usam 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`, exceto o próprio `context`. 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 = [[13, "v1", "v2"], [79, "v3", "v4"]]
ic = 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 = [[101, "v5", "v6"], [113, "v7", "v8"]]
ic.data = new_data
client.insert(context=ic)
qr = client.query("SELECT * FROM test_table ORDER BY key DESC")
assert qr.row_count == 4
assert qr.first_row[0] == 113
```

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

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

Os formatos de escrita são implementados para um número limitado de tipos. Na maioria dos casos, o ClickHouse Connect determina automaticamente o formato de escrita correto para uma coluna com base no primeiro valor de dados não nulo. Por exemplo, quando o primeiro valor de uma coluna `DateTime` é um inteiro, o cliente o trata como um segundo desde a epoch.

Normalmente, não é necessário substituir um formato de escrita, mas os métodos em `clickhouse_connect.datatypes.format` podem definir um globalmente. Wrappers de contêiner, como `Array`, `Nullable` e `LowCardinality`, preservam o comportamento de formatação do tipo do elemento.

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

| 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 | | |
| Interval\* | int | | Os valores são contagens de 64 bits com sinal na unidade do tipo interval. |
| String | str or bytes | | Uma coluna deve conter texto ou bytes de forma consistente. |
| FixedString | bytes | string | Valores String são preenchidos com bytes zero. Bytes vazios são gravados como bytes todos zero. |
| Enum\[8,16] | str or int | | Insira labels como strings ou seus valores inteiros subjacentes. |
| Date | datetime.date or datetime.datetime | int | Valores inteiros são interpretados como dias desde 1970-01-01. |
| Date32 | datetime.date or datetime.datetime | int | Valores inteiros são interpretados como deslocamentos de dias com sinal. |
| DateTime | datetime.datetime | int | Valores inteiros são interpretados como segundos desde a epoch. |
| DateTime64 | datetime.datetime | int | Valores inteiros são interpretados como ticks na precisão da coluna. |
| Time | datetime.timedelta | int, string, time | Valores inteiros são interpretados como segundos. |
| Time64 | datetime.timedelta | int, string, time | Há suporte às escalas de 0 a 9. Valores inteiros são interpretados como ticks na precisão da coluna. Valores timedelta do NumPy e inserções de DataFrame funcionam em todas as escalas. Os tipos time do Python são limitados a microssegundos. |
| 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 | | Use `()` para `Tuple()`. |
| Map | dict | | O formato de leitura `pairs` não altera as entradas de inserção. Use Arrow para preservar chaves duplicadas sem perdas em operações de ida e volta. |
| Nested | Sequence\[dict] | | |
| UUID | uuid.UUID | string | Strings formatadas corretamente podem ser inseridas como UUIDs do ClickHouse |
| JSON | dict | string | Há suporte a dicionários e strings de objetos JSON. O tipo legado `Object('json')` não é suportado. |
| Variant | object | | Os valores usam a serialização nativa do tipo membro. Use `clickhouse_connect.datatypes.dynamic.typed_variant` quando os tipos Python forem ambíguos. |
| Dynamic | object | | No momento, os valores são inseridos por meio de sua representação String. |
| MultiPoint | Sequence\[tuple] | | Cada ponto é uma tupla de 2 elementos. A inserção de valores MultiPoint exige o ClickHouse 26.8 ou posterior. |
| Geometry | tuple or list | | Valores Point são tuplas de 2 elementos. Envolva valores baseados em lista, incluindo MultiPoint, com `typed_variant` para selecionar um membro de geometria. |
| QBit | Sequence\[float] | | O NumPy é usado automaticamente para uma transposição de bits mais rápida quando instalado. |

<h4 id="date-and-date32-values">
  Valores Date e Date32
</h4>

Inserções nativas aceitam uma mistura de valores Python `date` e `datetime` em uma coluna `Date` ou `Date32`. Um `datetime` contribui com a sua própria data de calendário, conforme retornada por `.date()`, sem conversão de fuso horário. Isso também vale para valores dentro de colunas `Nullable`, `Array`, `Tuple` e `LowCardinality`.

```python theme={null}
from datetime import date, datetime, timedelta, timezone

value = datetime(2024, 1, 1, 0, 30, tzinfo=timezone(timedelta(hours=14)))
client.command("CREATE TABLE event_dates (event_date Date) ENGINE Memory")
client.insert("event_dates", [[value], [date(2024, 1, 2)]])

result = client.query("SELECT event_date FROM event_dates ORDER BY event_date")
assert result.result_rows == [(date(2024, 1, 1),), (date(2024, 1, 2),)]
```

Isso se aplica a objetos Python, incluindo colunas `object` do Pandas. Colunas `datetime64` do Pandas com fuso horário usam a data de calendário em UTC. Para preservar as datas de calendário originais, converta esses valores em objetos Python `date` antes da inserção. Valores `datetime64` do NumPy não têm metadados de fuso horário.

Parâmetros de consulta do tipo datetime seguem as [regras de vinculação](/pt-BR/integrations/language-clients/python/driver-api#parameters-argument). Um `datetime` com fuso horário é convertido para o fuso horário do servidor antes de ser formatado como valor `Date` ou `Date32`, o que pode alterar a data de calendário. Passe `value.date()` explicitamente quando uma inserção e um parâmetro vinculado precisarem usar a mesma data de calendário.

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

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

* `insert_df` -- Insere um DataFrame do Pandas como dados Native orientados a colunas. Também oferece suporte a nomes/tipos de coluna explícitos ou a um `InsertContext` reutilizável.
* `insert_arrow` -- Insere uma tabela PyArrow usando o formato de entrada Arrow do ClickHouse.
* `insert_df_arrow` -- Insere um DataFrame do Pandas com Arrow como backend ou um DataFrame do Polars. Todas as colunas do Pandas devem usar backends `dtype` baseados em Arrow.

Todos os três métodos aceitam `database`, `settings` e `transport_settings` de HTTP por solicitação.

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

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

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

client = clickhouse_connect.get_client()

df = pd.DataFrame({
    "id": [13, 79],
    "name": ["user_1", "user_2"],
    "age": [25, 30],
})

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

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

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

client = clickhouse_connect.get_client()

arrow_table = pa.table({
    "id": [13, 79],
    "name": ["user_1", "user_2"],
    "age": [25, 30],
})

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

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

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

client = clickhouse_connect.get_client()

# Convert to Arrow-backed dtypes for better performance
df = pd.DataFrame({
    "id": [13, 79],
    "name": ["user_1", "user_2"],
    "age": [25, 30],
}).convert_dtypes(dtype_backend="pyarrow")

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

<h3 id="create-table-from-pyarrow-schema">
  Criar uma tabela a partir de um esquema do PyArrow
</h3>

`create_table_from_arrow_schema` gera uma instrução `CREATE TABLE` a partir de campos escalares comuns do Arrow. O mapeamento abrange inteiros com e sem sinal, valores de ponto flutuante, booleanos, strings, datas e timestamps. Ele cria intencionalmente colunas do ClickHouse que não permitem NULL e gera `TypeError` para tipos do Arrow sem suporte, portanto revise o DDL gerado antes de executá-lo.

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

from clickhouse_connect.driver.ddl import create_table_from_arrow_schema

client = clickhouse_connect.get_client()
schema = pa.schema(
    [
        ("id", pa.uint32()),
        ("name", pa.string()),
        ("event_time", pa.timestamp("ms", tz="UTC")),
    ]
)
ddl = create_table_from_arrow_schema(
    table_name="arrow_events",
    schema=schema,
    engine="MergeTree",
    engine_params={"ORDER BY": "id"},
)
client.command(ddl)
```

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

Ao inserir objetos `datetime` do Python em colunas `DateTime` ou `DateTime64`, o ClickHouse Connect os converte em valores de epoch.

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

Objetos com fuso horário preservam o instante representado. O fuso horário de origem não precisa coincidir com o fuso horário definido na coluna do ClickHouse.

```python theme={null}
from datetime import datetime, timezone
from zoneinfo import ZoneInfo

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

data = [
    [datetime(2023, 6, 15, 10, 30, tzinfo=timezone.utc)],
    [datetime(2023, 6, 15, 10, 30, tzinfo=ZoneInfo("America/Denver"))],
    [datetime(2023, 6, 15, 10, 30, tzinfo=ZoneInfo("Asia/Tokyo"))],
]

client.insert("events", data, column_names=["event_time"])
results = client.query(
    "SELECT event_time FROM events ORDER BY event_time",
    query_tz="UTC",
    tz_mode="aware",
)
assert [row[0].hour for row in results.result_rows] == [1, 10, 16]
```

<Note>
  O ClickHouse Connect usa o módulo `zoneinfo` da biblioteca padrão. O driver não depende mais de `pytz`.
</Note>

<h4 id="timezone-naive-datetime-objects">
  Objetos datetime sem fuso horário
</h4>

A configuração global `naive_datetime_insert` controla inserções nativas de objetos Python com valores `datetime` sem fuso horário. Ela também se aplica a strings ISO sem fuso horário aceitas por colunas `DateTime64`.

* `"local"` é o padrão na versão 1.x. O Python interpreta o valor no fuso horário do processo quando `.timestamp()` é chamado. Isso preserva o comportamento atual.
* `"server"` interpreta o valor como hora do relógio no fuso horário declarado pela coluna `DateTime` ou `DateTime64`. Se a coluna não tiver fuso horário, usa o fuso horário do servidor informado quando o cliente se conectou.

Defina a opção antes de uma inserção. Ela é lida quando cada coluna de inserção nativa que contém objetos `datetime` do Python ou strings ISO `DateTime64` é serializada; portanto, a alteração se aplica a clientes existentes e contextos de inserção reutilizáveis.

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

from clickhouse_connect import common

common.set_setting("naive_datetime_insert", "server")

naive_time = datetime(2023, 6, 15, 10, 30)
client.insert("events", [[naive_time]], column_names=["event_time"])
```

Com `"server"`, o ClickHouse Connect associa o `tzinfo` de destino antes de converter o valor em epoch. Para fusos horários IANA, segue as regras da biblioteca padrão para transições de horário de verão. Uma sobreposição no outono usa o valor `fold` do `datetime`. Por padrão, `fold=0` seleciona o deslocamento anterior à transição, enquanto `fold=1` seleciona o deslocamento posterior. Uma lacuna na primavera usa a mesma seleção de deslocamento e não é rejeitada nem normalizada.

Horários de relógio inexistentes na lacuna da primavera podem não ser preservados em uma conversão de ida e volta por meio de um parâmetro de consulta no modo de relógio, pois a análise de texto do ClickHouse pode selecionar um deslocamento diferente. Use um `datetime` com fuso horário ou um horário de relógio válido quando o instante for importante.

A opção se aplica apenas a inserções nativas de objetos Python `datetime` e strings ISO sem fuso horário aceitas por `DateTime64`. Colunas NumPy e Pandas com dtype `datetime64` sem fuso horário mantêm a conversão existente de horário de relógio em UTC.

Para representar um instante específico independentemente de qualquer modo, associe o fuso horário desejado ou forneça explicitamente um inteiro epoch.

```python theme={null}
from datetime import datetime, timezone

utc_time = datetime(2023, 6, 15, 10, 30, tzinfo=timezone.utc)
client.insert("events", [[utc_time]], column_names=["event_time"])

naive_time = datetime(2023, 6, 15, 10, 30)
epoch_timestamp = int(naive_time.replace(tzinfo=timezone.utc).timestamp())
client.insert("events", [[epoch_timestamp]], column_names=["event_time"])
```

Parâmetros de consulta `datetime` sem fuso horário usam a configuração separada `naive_datetime_binding`. O modo padrão `"wall"` envia os campos de data e hora sem conversão para o horário local do host. Consulte a seção [argumento Parameters](/pt-BR/integrations/language-clients/python/driver-api#parameters-argument).

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

As colunas do ClickHouse podem declarar metadados de fuso horário, por exemplo `DateTime('America/Denver')` ou `DateTime64(3, 'Asia/Tokyo')`. Esses metadados controlam como os valores são apresentados quando são consultados.

Ao inserir um valor com fuso horário, o ClickHouse Connect preserva o instante representado. Para um valor sem fuso horário, a configuração `naive_datetime_insert` controla se é usado o fuso horário do processo ou o da coluna. Ao consultar, o resultado usa o fuso horário da coluna, a menos que seja fornecido um override por coluna com o argumento `column_tzs`. O argumento `query_tz` não substitui o fuso horário declarado de uma coluna.

```python theme={null}
from datetime import datetime
from zoneinfo import ZoneInfo

client.command(
    "CREATE TABLE events_with_timezone "
    "(event_time DateTime('America/Los_Angeles')) "
    "ENGINE Memory"
)

data = datetime(2023, 6, 15, 10, 30, tzinfo=ZoneInfo("America/New_York"))
client.insert("events_with_timezone", [[data]], column_names=["event_time"])

result = client.query("SELECT event_time FROM events_with_timezone")
returned = result.first_row[0]
assert returned.hour == 7
assert returned.tzinfo == ZoneInfo("America/Los_Angeles")
```

<h2 id="file-inserts">
  Inserções de arquivo
</h2>

`clickhouse_connect.driver.tools.insert_file` transmite um arquivo local para uma tabela existente em fluxo e delega o parsing ao ClickHouse.

| Parâmetro | Tipo | Padrão | Descrição |
| - | - | - | - |
| `client` | `Client` | Obrigatório | Client síncrono usado para a inserção. |
| `table` | str | Obrigatório | Tabela de destino simples ou qualificada com o database. |
| `file_path` | str | Obrigatório | Caminho local para o arquivo de entrada. |
| `fmt` | str | `"CSV"` ou `"CSVWithNames"` | Formato de entrada. O padrão é `"CSV"` quando `column_names` é fornecido e `"CSVWithNames"` caso contrário. |
| `column_names` | Sequence\[str] | `None` | Colunas representadas pelo arquivo. Não é necessário para formatos que incluem nomes. |
| `database` | str | `None` | Database de destino quando a tabela não é qualificada. |
| `settings` | dict | `None` | Consulte [Argumento `settings`](/pt-BR/integrations/language-clients/python/driver-api#settings-argument-1). |
| `compression` | str | `None` | Compressão existente do arquivo, como `"zstd"`, `"lz4"` ou `"gzip"`. `gzip` é inferido a partir de nomes de arquivo `.gz` e `.gzip`. |

Configurações de formato de entrada, como `input_format_allow_errors_ratio` e `input_format_allow_errors_num`, podem ser passadas por meio de `settings`.

```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": 0.2,
        "input_format_allow_errors_num": 5,
    },
)
```

Para um `AsyncClient`, use `await` com `insert_file_async` e os mesmos argumentos:

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

await insert_file_async(async_client, "example_table", "my_data.csv")
```

O helper assíncrono lê o arquivo em uma thread de trabalho antes de aguardar o `raw_insert`, portanto o conteúdo do arquivo permanece na memória.
