SQL ОБНОВЛЕНИЕ порядок оценки
Каков порядок оценки в следующем запросе:
UPDATE tbl SET q = q + 1, p = q;
То есть будет "tbl"."p"
быть установленным q
или же q + 1
? Порядок оценки здесь регулируется стандартом SQL?
Благодарю.
ОБНОВИТЬ
После рассмотрения ответа Мигса я провел несколько тестов на всех БД, которые смог найти. Хотя я не знаю, что говорится в стандарте, реализации могут отличаться.
Дано
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
ОБНОВЛЕНИЕ 2
Firebird 2.5 меняет свое поведение, чтобы соответствовать большинству других SQL-движков, которые я тестировал, оставляя MySQL в покое. Соответствующая запись примечаний к выпуску "Логическое изменение в предложении SET" настоятельно рекомендует, чтобы поведение большинства было правильным в соответствии со спецификациями SQL.
Я прослушал MySQL, чтобы прокомментировать это поведение (ошибка № 52861), так как они кажутся выбросами.
ОБНОВЛЕНИЕ 3
Вышеупомянутая ошибка сегодня (2010-05-19) закрыта, и документация должна быть обновлена, чтобы сделать это поведение явным как в описании ОБНОВЛЕНИЯ, так и в разделе Отличия от стандартного SQL.
Браво, MySQL.
3 ответа
MySQL выполняет оценку "слева направо" и "видит" новые значения. (Протестировано на 5.0.45-community-nt-log MySQL Community Edition)
Кроме того, из руководства MySQL: "Назначения UPDATE для одной таблицы обычно оцениваются слева направо. Для обновлений для нескольких таблиц нет гарантии, что назначения выполняются в каком-либо конкретном порядке".
Теперь "в целом" довольно расплывчато, а "без гарантий" очень плохо, учитывая, что порядок оценки важен.
Итак, чтобы ответить на вопрос: определяется ли поведение "стандартом SQL" или это просто соглашение?
ОБНОВЛЕНИЕ: Получил спецификации SQL92, которые в состоянии "13.10 оператор обновления: поиск" элемент "6) (выражение значения) эффективно оцениваются для каждой строки T перед обновлением любой строки T".
ИМХО не совсем однозначно, но достаточно, чтобы учесть, что СТАНДАРТ НЕ "видеть" результаты вашего собственного обновления. Рассмотрим ваш пример, как это делают Oracle, PostgreSQL и Interbase.
UPDATE
не видит результатов своей работы.
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
Запись в таблицу должна произойти после транзакции, которая прошла успешно, когда чтение было завершено.