Skip to main content

insert-into

INSERT INTO​

Добавляет данные в таблицу.

Синтаксис

INSERT INTO [db.]table [(c1, c2, c3)] VALUES (v11, v12, v13), (v21, v22, v23), ...

Вы можете указать список столбцов для вставки, используя синтаксис (c1, c2, c3). Также можно использовать выражение cо звездочкой и/или модификаторами, такими как APPLY, EXCEPT, REPLACE.

В качестве примера рассмотрим таблицу:

SHOW CREATE insert_select_testtable
CREATE TABLE insert_select_testtable
(
`a` Int8,
`b` String,
`c` Int8
)
ENGINE = MergeTree()
ORDER BY a
INSERT INTO insert_select_testtable (*) VALUES (1, 'a', 1)

Если вы хотите вставить данные во все столбцы, кроме 'b', вам нужно передать столько значений, сколько столбцов вы указали в скобках:

INSERT INTO insert_select_testtable (* EXCEPT(b)) Values (2, 2)
SELECT * FROM insert_select_testtable
┌─a─┬─b─┬─c─┐
│ 2 │ │ 2 │
└───┴───┴───┘
┌─a─┬─b─┬─c─┐
│ 1 │ a │ 1 │
└───┴───┴───┘

В этом примере мы видим, что вторая строка содержит столбцы a и c, заполненные переданными значениями и b, заполненный значением по умолчанию. Также можно использовать ключевое слово DEFAULT для вставки значений по умолчанию:

INSERT INTO insert_select_testtable VALUES (1, DEFAULT, 1) ;

Если список столбцов не включает все существующие столбцы, то все остальные столбцы заполняются следующим образом:

  • Значения, вычисляемые из DEFAULT выражений, указанных в определении таблицы.
  • Нули и пустые строки, если DEFAULT не определены.

В INSERT можно передавать данные любого формата, который поддерживает ClickHouse. Для этого формат необходимо указать в запросе в явном виде:

INSERT INTO [db.]table [(c1, c2, c3)] FORMAT format_name data_set

Например, следующий формат запроса идентичен базовому варианту INSERT … VALUES:

INSERT INTO [db.]table [(c1, c2, c3)] FORMAT Values (v11, v12, v13), (v21, v22, v23), ...

ClickHouse отсекает все пробелы и один перенос строки (если он есть) перед данными. Рекомендуем при формировании запроса переносить данные на новую строку после операторов запроса (это важно, если данные начинаются с пробелов).

Пример:

INSERT INTO t FORMAT TabSeparated
11 Hello, world!
22 Qwerty

С помощью консольного клиента или HTTP интерфейса можно вставлять данные отдельно от запроса. Как это сделать, читайте в разделе «Интерфейсы».

Ограничения (constraints)​

Если в таблице объявлены ограничения, то их выполнимость будет проверена для каждой вставляемой строки. Если для хотя бы одной строки ограничения не будут выполнены, запрос будет остановлен.

Вставка результатов SELECT​

Синтаксис

INSERT INTO [db.]table [(c1, c2, c3)] SELECT ...

Соответствие столбцов определяется их позицией в секции SELECT. При этом, их имена в выражении SELECT и в таблице для INSERT, могут отличаться. При необходимости выполняется приведение типов данных, эквивалентное соответствующему оператору CAST.

Все форматы данных кроме Values не позволяют использовать в качестве значений выражения, такие как now(), 1 + 2 и подобные. Формат Values позволяет ограниченно использовать выражения, но это не рекомендуется, так как в этом случае для их выполнения используется неэффективный вариант кода.

Не поддерживаются другие запросы на модификацию части данных: UPDATE, DELETE, REPLACE, MERGE, UPSERT, INSERT UPDATE. Вы можете удалять старые данные с помощью запроса ALTER TABLE ... DROP PARTITION.

Для табличной функции input() после секции SELECT должна следовать секция FORMAT.

Чтобы вставить значение по умолчанию вместо NULL в столбец, который не позволяет хранить NULL, включите настройку insert_null_as_default.

Вставка данных из файла​

Синтаксис

INSERT INTO [db.]table [(c1, c2, c3)] FROM INFILE file_name [COMPRESSION type] FORMAT format_name

Используйте этот синтаксис, чтобы вставить данные из файла, который хранится на стороне клиента. file_name и type задаются в виде строковых литералов. Формат входного файла должен быть задан в секции FORMAT.

Поддерживаются сжатые файлы. Формат сжатия определяется по расширению файла, либо он может быть задан в секции COMPRESSION. Поддерживаются форматы: 'none', 'gzip', 'deflate', 'br', 'xz', 'zstd', 'lz4', 'bz2'.

Эта функциональность поддерживается клиентом командной строки и clickhouse-local.

Пример

Выполните следующие запросы, используя клиент командной строки:

echo 1,A > input.csv ; echo 2,B >> input.csv
clickhouse-client --query="CREATE TABLE table_from_file (id UInt32, text String) ENGINE=MergeTree() ORDER BY id;"
clickhouse-client --query="INSERT INTO table_from_file FROM INFILE 'input.csv' FORMAT CSV;"
clickhouse-client --query="SELECT * FROM table_from_file FORMAT PrettyCompact;"

Результат:

┌─id─┬─text─┐
│ 1 │ A │
│ 2 │ B │
└────┴──────┘

Вставка в табличную функцию​

Данные могут быть вставлены в таблицы, заданные с помощью табличных функций.

Синтаксис

INSERT INTO [TABLE] FUNCTION table_func ...

Пример

Табличная функция remote используется в следующих запросах:

CREATE TABLE simple_table (id UInt32, text String) ENGINE=MergeTree() ORDER BY id;
INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table)
VALUES (100, 'inserted via remote()');
SELECT * FROM simple_table;

Результат:

┌──id─┬─text──────────────────┐
│ 100 │ inserted via remote() │
└─────┴───────────────────────┘

Замечания о производительности​

INSERT сортирует входящие данные по первичному ключу и разбивает их на партиции по ключу партиционирования. Если вы вставляете данные в несколько партиций одновременно, то это может значительно снизить производительность запроса INSERT. Чтобы избежать этого:

  • Добавляйте данные достаточно большими пачками. Например, по 100 000 строк.
  • Группируйте данные по ключу партиционирования самостоятельно перед загрузкой в ClickHouse.

Снижения производительности не будет, если:

  • Данные поступают в режиме реального времени.
  • Вы загружаете данные, которые как правило отсортированы по времени.

Также возможно вставлять данные асинхронно во множественных маленьких вставках. Данные от таких вставок сначала собираются в пачки, а потом вставляются в таблицу. Чтобы включить асинхронный режим, используйте настройку async_insert. Обратите внимание, что асинхронные вставки поддерживаются только через протокол HTTP, а дедупликация при этом не производится.

См. также