SQL ОБНОВЛЕНИЕ порядок оценки - PullRequest
36 голосов
/ 05 февраля 2010

Каков порядок оценки в следующем запросе:

UPDATE tbl SET q = q + 1, p = q;

То есть для "tbl"."p" будет установлено значение q или q + 1? Порядок оценки здесь регулируется стандартом SQL?

Спасибо.

UPDATE

После рассмотрения ответа Мига я провел несколько тестов на всех БД, которые смог найти. Хотя я не знаю, что говорится в стандарте, реализации могут отличаться.

Учитывая

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 секция.

Bravo, MySQL.

Ответы [ 3 ]

13 голосов
/ 14 апреля 2010

MySQL выполняет оценку «слева направо» и «видит» новые значения. (Проверено на 5.0.45-community-nt-log MySQL Community Edition)

Кроме того, из руководства MySQL: «Назначения UPDATE для одной таблицы обычно оцениваются слева направо. Для обновлений для нескольких таблиц нет гарантии, что назначения выполняются в каком-либо конкретном порядке».

Теперь "в целом" довольно расплывчато, а "без гарантий" очень плохо, учитывая важность порядка оценки.

Итак, чтобы ответить на вопрос: соответствует ли поведение "стандарту SQL" или это просто соглашение?


ОБНОВЛЕНИЕ: Получил спецификации SQL92, в которых указано "13.10 оператор обновления: поиск" элемента "6) (выражение значения) эффективно оцениваются для каждой строки Т перед обновлением любой строки Т."

ИМХО не совсем однозначно, но достаточно, чтобы учесть, что СТАНДАРТ НЕ "видит" результаты вашего собственного обновления. С учетом вашего примера, как это делают Oracle, PostgreSQL и Interbase.

6 голосов
/ 05 февраля 2010

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
0 голосов
/ 05 февраля 2010

Запись в таблицу должна выполняться после транзакции, которая успешно выполнялась после завершения чтения.

...