Что является порядком оценки в следующем запросе:
UPDATE tbl SET q = q + 1, p = q;
Таким образом, будет "tbl"."p"
будьте установлены на q
или q + 1
? Порядком оценки здесь управляет стандарт SQL?
Спасибо.
После рассмотрения ответа МиГов я запустил некоторые тесты на всем DBS, который я мог найти. В то время как я не знаю то, что говорит стандарт, реализации варьируются.
Данный
CREATE TABLE tbl (p INT NOT NULL, q INT NOT NULL);
INSERT INTO tbl VALUES (1, 5); -- p := 1, q := 5
UPDATE tbl SET q = q + 1, p = q;
Я нашел значения "p"
и "q"
были:
database p q
-----------------+---+---
Firebird 2.1.3 | 6 | 6 -- But see "Update 2" below
InterBase 2009 | 5 | 6
MySQL 5.0.77 | 6 | 6 -- See "Update 3" below
Oracle XE (10g) | 5 | 6
PostgreSQL 8.4.2 | 5 | 6
SQLite 3.3.6 | 5 | 6
SQL Server 2016 | 5 | 6
Firebird 2.5 изменяет свое поведение для соответствия большинству других механизмов SQL, которые я протестировал, оставив MySQL в покое. Соответствующая запись Информации о версии, "Логическое Изменение в Пункте НАБОРА", убедительно предполагает, что поведение большинства корректно на спецификации SQL.
Я прослушивал MySQL для комментария этого поведения (ошибка № 52861), поскольку они, кажется, изолированная часть.
Вышеупомянутая ошибка сегодня (2010-05-19) закрыта, и набор документации, который будет обновлен для создания этого поведения явным и в описании ОБНОВЛЕНИЯ и в разделе Differences from Standard SQL.
Браво, MySQL.
MySQL выполняет оценку "слева направо" и "видит" новые значения. (Проверено на 5.0.45-community-nt -log MySQL Community Edition)
Кроме того, из руководства MySQL: «Назначения UPDATE для одной таблицы обычно оцениваются слева направо. Для обновлений нескольких таблиц нет гарантии, что назначения выполняются в каком-либо конкретном порядке.
«Обычно» довольно расплывчато, а «отсутствие гарантии» - это очень плохо, учитывая, что порядок оценки важен.
Итак, чтобы ответить на вопрос: ЯВЛЯЕТСЯ ли поведение, определенным «стандартом SQL», или это просто соглашение?
ОБНОВЛЕНИЕ: Получил спецификации SQL92, в которых указано «Оператор обновления 13.10: найден» item "6) (выражение значения) эффективно оцениваются для каждой строки T перед обновлением любой строки T."
ИМХО не совсем однозначно, но достаточно, чтобы принять во внимание, что СТАНДАРТ НЕ предназначен для "просмотра" результатов ваше собственное обновление. Рассматривая ваш пример, как это делают Oracle, PostgreSQL и Interbase.
ОБНОВЛЕНИЕ
не видит результатов своей работы.
p
будет установлено на q
до обновления.
Следующий код просто меняет местами столбцы:
DECLARE @test TABLE (p INT, q INT)
INSERT
INTO @test
VALUES (2, 3)
SELECT *
FROM @test
p q
--- ---
2 3
UPDATE @test
SET p = q,
q = p
SELECT *
FROM @test
p q
--- ---
3 2
Запись в таблицу должна происходить после транзакции, которая уже выполнялась, когда чтение было завершено.