Разберите ситуацию: при добавлении строк в таблицу результатом выборки из неё самой будут ли вновь добавленные строки повторно обработаны тем же оператором?
Нет. В рамках одного оператора INSERT ... SELECT набор строк-источник формируется как результат запроса до применения вставки; строки, добавленные этим же оператором, не становятся новыми строками-источниками для повторной обработки. Поэтому оператор не размножает данные бесконечно.
SQL задуман как декларативный язык: запрос описывает множество строк, а не последовательность пошаговых команд. Такое разделение чтения и изменения устраняет зависимость результата от физического порядка обработки строк и позволяет СУБД выбирать план выполнения.
Для операций, совмещающих чтение и запись, это особенно важно. Если бы вставленные строки могли тут же снова участвовать в источнике, результат зависел бы от порядка обхода и мог бы не завершиться.
Самоссылочная вставка может использоваться для создания копий строк, например при переносе записей в другой раздел той же таблицы. Ошибочно ожидать, что новые строки будут снова выбраны, — значит неверно оценить количество вставок и риск дублирования данных.
Отдельно нужно учитывать ограничения: уникальные ключи, внешние ключи, триггеры и другие ограничения могут сделать вставку ошибочной, даже если набор строк-источник определён однозначно.
Логически сначала вычисляется запрос-источник, включая его фильтрацию и выражения. Затем полученный набор передаётся операции вставки. Вставленные строки не добавляются обратно в уже вычисленный набор источника этого же оператора.
Если до выполнения в таблице были строки с идентификаторами 1 и 2, оператор попытается вставить ровно две строки: с идентификаторами 101 и 102. Строки 101 и 102 не удовлетворяют источнику повторно в рамках того же оператора, даже если после вставки они формально подходят под его условие.
Это не означает, что все СУБД разрешают любую самоссылочную вставку: конкретная система может предъявлять требования к ограничениям, триггерам или блокировкам. Кроме того, триггер может выполнять дополнительные операции, поэтому итоговое состояние таблицы иногда включает изменения, не являющиеся непосредственно строками основного INSERT.
В таблице хранятся шаблоны задач, и нужно создать копии задач с новыми идентификаторами. Разработчик опасался, что выборка из той же таблицы будет последовательно находить уже созданные копии и породит дополнительные записи.
Рассматривались два варианта. Самоссылочная вставка компактна и атомарна, но требует внимательно проверить уникальные ключи и правила генерации идентификаторов. Сначала выгрузить исходные строки во временную таблицу проще для отладки, однако это добавляет промежуточное хранение и усложняет транзакцию.
Выбрали один INSERT ... SELECT с явным условием отбора и заранее рассчитанными идентификаторами. Результат оказался предсказуемым: число вставленных строк совпало с числом строк исходной выборки, а новые копии не обрабатывались повторно.
Вопрос: Можно ли считать, что строки источника читаются физически до начала вставки?
Ответ: Не обязательно. Это правило описывает логическую семантику, а не физический план. СУБД может читать и записывать данные в оптимизированном порядке, но результат должен соответствовать логической модели оператора.
Вопрос: Что изменится, если триггер после вставки создаёт дополнительные строки в той же таблице?
Ответ: Такие строки могут появиться из-за работы триггера, но они не становятся новыми строками источника уже выполняющегося INSERT. При этом триггер способен вызвать дополнительные операции, ограничения или каскады, поэтому итоговый эффект нужно анализировать отдельно от основного запроса.
Вопрос: Почему явный список столбцов особенно важен в самоссылочной вставке?
Ответ: Он фиксирует соответствие выражений целевым столбцам и защищает запрос от изменения физического порядка столбцов или добавления новых столбцов в таблицу. Без такого списка легко случайно вставить значения не в те столбцы либо получить ошибку при изменении схемы.