Clickhouse рассчитывает автоинкремент - PullRequest
0 голосов
/ 04 августа 2020

Существует устаревшая таблица со столбцом целочисленного идентификатора.

Попытка воспроизвести автоинкремент:

INSERT legacy_table (id, name)
SELECT
    (SELECT max(id) FROM legacy_table) + rowNumberInAllBlocks() id,
    name
FROM other_table

Проблема в том, что SELECT max(id) FROM legacy_table вычисляется один раз и может порождать дубликаты.

Можно выполнить SELECT max(id) для каждой строки или другое решение для автоинкремента?

1 Ответ

1 голос
/ 05 августа 2020

Я бы полагался на функции массива, чтобы сделать поведение предсказуемым.

Примечания:

  • не должно быть никаких внешних вставок в таблицы назначения и исходные таблицы

  • должен запускаться только один скрипт за раз (поэтому не применяйте его к распределенной таблице, а последовательно выполняйте на каждом сегменте)

  • для огромная таблица, вложенный запрос может завершиться неудачно, поэтому имеет смысл добавить предложение WHERE, чтобы ограничить количество обрабатываемых данных

INSERT INTO target
SELECT result.1 AS id, result.2 AS name
FROM (
  WITH (SELECT max(id) FROM target) AS target_table_max_id
  SELECT 
    groupArray((id, name)) origin_data,
    arrayMap((origin_row, row_index) -> (target_table_max_id + row_index, origin_row.2), 
      origin_data, 
      arrayEnumerate(origin_data)) origin_data_updated,
    arrayJoin(origin_data_updated) result
  FROM origin);

Скрипты для подготовки тестовой среды:

# prepare test tables
CREATE TABLE target (`id` Int32, `name` String) ENGINE = Memory;
CREATE TABLE origin (`id` Int32, `name` String) ENGINE = Memory; 

# fill test tables 
INSERT INTO target 
SELECT  number AS id, toString(id) AS name
FROM numbers(8);

INSERT INTO origin 
SELECT number + 2048 AS id, toString(id) AS name
FROM numbers(4);
...