Почему порядок вычисления для выражений с участием пользовательских переменных не определен?
Из руководства MySQL вывод следующего запроса не всегда будет одинаковым.
SET @a := 0;
SELECT
@a AS first,
@a := @a + 1 AS second,
@a := @a + 1 AS third,
@a := @a + 1 AS fourth,
@a := @a + 1 AS fifth,
@a := @a + 1 AS sixth;
Выход:
first second third fourth fifth sixth
0 1 2 3 4 5
Цитирование из руководства:
Однако порядок вычисления для выражений с участием пользовательских переменных не определен;
Я хочу знать историю позади.
Итак, мой вопрос: почему порядок вычисления для выражений, включающих пользовательские переменные, не определен?
3 ответа
Порядок оценки выражений в select
не определено По большей части вы замечаете это только когда у вас есть переменные, потому что ошибки приводят к ошибочной информации.
Зачем? Стандарт SQL не требует порядка оценки, поэтому каждая база данных может решать, как оценивать выражения. Обычно такие решения остаются за оптимизатором.
TL;DR Пользовательские переменные MySQL не предназначены для такого использования. Оператор SQL описывает набор результатов, а не последовательность операций. В документации неясно, что вообще означают назначения переменных. Но вы не можете одновременно читать и писать переменные. И порядок назначения в предложении SELECT не определен. И все, что вы можете предположить, это то, что присваивания во внешнем предложении SELECT выполняются для какой-то одной выходной строки.
Почти весь код, который вы видите как свой, имеет неопределенное поведение. Некоторые разумные люди демонстрируют с помощью кода реализации для операторов и оптимизации, что на самом деле делает конкретная реализация. Но на это поведение нельзя положиться в следующем выпуске.
Прочитайте документацию. Чтение и запись одной и той же переменной не определены. Когда это не сделано, любая переменная чтения фиксируется в инструкции. Нет заказа на назначения. Для SELECT только с ДЕТЕРМИНИСТИЧЕСКИМИ функциями (значения которых определяются значениями аргументов) результат определяется концептуальным выполнением оценки. Но нет никакой связи между этим и пользовательской переменной. Что когда-либо означает назначение, непонятно: в документе сказано, что "каждое выражение выбора оценивается только при отправке клиенту". Кажется, это говорит о том, что нет никакой гарантии, что строка даже "выбрана", за исключением того, что она помещена в результирующий набор согласно крайнему предложению SELECT. Порядок назначений в SELECT не определен. И даже если назначения концептуально выполняются для каждой строки, они могут зависеть только от значения строки, так что это то же самое, что сказать, что назначение выполняется только один раз для некоторой строки. А поскольку порядок назначения не определен, эта строка может быть любой строкой. Таким образом, предполагая, что это означает, что документация означает, что все, что вы можете ожидать, это то, что если вы не читаете и не пишете из одной и той же переменной в операторе SELECT, то каждое присвоение переменной в самом внешнем SELECT будет происходить в некотором порядке для одной выходной строки.,
Это зависит от решения оптимизатора базы данных. Вот почему это неясно. Но в основном оптимизатор решает, как мы прогнозируем результат.