Как выполнить операцию вставки данных с обновлением первичного ключа?

Как выполнить вставку данных без использования row_id, или с обновлением row_id, взяв данные из другой таблицы? Учитывая, что на этом поле установлен индекс, мне хотелось бы избежать затрат на пересоздание индекса и не отключать его. Вот пример запроса:  
Insert into * table  
From * table2  
Select * from table2  
Where pole = 2.
  • 7 февраля 2025 г. 8:54
Ответы на вопрос 2
Для выполнения операции вставки данных с обновлением первичного ключа (например, `row_id`) вы можете использовать SQL-запросы. Однако чтобы обеспечить уникальность первичного ключа при вставке, необходимо определить, как генерировать новые значения для первичного ключа.

Если вы хотите вставить данные из одной таблицы в другую, при этом не нарушая уникальности первичного ключа, есть несколько способов. Один из подходов заключается в использовании специальной функции (например, `NEWID()`, если вы используете SQL Server для генерации уникальных идентификаторов) или просто в использовании последующего значения, если `row_id` является числовым.

Вот общий пример для SQL Server:

1. **Использование NEWID() для создания уникального значения:** Если ваш первичный ключ - это идентификатор GUID, вы можете использовать такой запрос:

```sql
INSERT INTO table (row_id, column1, column2, ...)
SELECT NEWID(), column1, column2, ...
FROM table2
WHERE pole = 2;
```

2. **Использование последовательностей для числовых идентификаторов:** Если ваш первичный ключ - это числовое значение, вы можете использовать последовательность (если вы используете PostgreSQL или Oracle) или конструкцию получения следующего значения (например, `MAX(row_id) + 1`), но это не всегда безопасно из-за возможных гонок:

```sql
INSERT INTO table (row_id, column1, column2, ...)
SELECT (SELECT COALESCE(MAX(row_id), 0) + ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) 
        FROM table) AS new_row_id, 
        column1, column2, ...
FROM table2
WHERE pole = 2;
```

3. **Клонирование с обновлением первичного ключа:** Если вы хотите просто скопировать данные из одной таблицы в другую и обновить первичный ключ:

```sql
INSERT INTO table (row_id, column1, column2, ...)
SELECT (SELECT ISNULL(MAX(row_id), 0) + ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
        FROM table) AS new_row_id, 
        column1, column2, ...
FROM table2
WHERE pole = 2;
```

Обратите внимание, что использование `ROW_NUMBER()` генерирует новую последовательность, обеспечивая уникальность, но может привести к конкуренции, если несколько пользователей выполняют вставку одновременно. Также стоит проверить, чтобы `row_id` не пересекался с уже существующими значениями.

4. **Работа с ограничениями на уровне базы данных:** Если вы хотите вставить данные, не нарушая ограничения уникальности, убедитесь, что ваше новое значение `row_id` уникально особенно в контексте параллельных вставок.

Также рекомендуется перед выполнением вставки делать резервные копии данных и тестировать запросы на небольших объемах данных, чтобы избежать непредвиденных ошибок.
Забудь про звёзды. Никаких SELECT * - только список конкретных полей. То же и в случае INSERT - перечисляй все поля, в которые идёт вставка. Единственное место, где может быть звезда как список полей - это в COUNT(*) . 

Соответственно поле синтетического первичного ключа в список полей - не включать.
INSERT INTO new_table (column1, column2, ...)
SELECT column1, column2, ...
FROM old_table
WHERE ... ;
Похожие вопросы