Ответ 1
статья KB, уже связанная с VanDerNorth, включает в себя строку
Правильное поведение для запроса совокупной конкатенации undefined.
но затем переходит к мутной воде немного, предоставляя обходное решение, которое, как представляется, указывает на детерминированное поведение.
Чтобы достичь ожидаемых результатов от совокупности запрос конкатенации, применяйте любую функцию Transact-SQL или выражение для столбцы в списке SELECT, а не в предложении ORDER BY.
Ваш проблемный запрос не применяет никаких выражений к столбцам в предложении ORDER BY
.
В статье 2005 "Заказы" в SQL Server... указано
Для обеспечения обратной совместимости SQL Server обеспечивает поддержку присвоения типа SELECT @p = @p + 1... ORDER BY в самом верхнем сфера.
В планах, где конкатенация работает так, как вы ожидали, вычисляющий скаляр с выражением [Expr1003] = Scalar Operator([@x]+[Expr1004])
появляется над сортировкой.
В плане, где он не работает, вычислительный скаляр появляется под сортировкой. Как объясняется в этот элемент соединения с 2006 года, когда выражение @x = @x + [msg]
появляется под сортировкой, оно оценивается для каждой строки, но все оценки заканчиваются использованием значения предварительного присваивания @x
. В другом аналогичном элементе подключения от 2006 года ответ от Microsoft говорил об "исправлении" проблемы.
Ответ Microsoft на все более поздние элементы Connect в этой проблеме (и их много) утверждают, что это просто не гарантируется
мы не делаем никаких гарантий относительно правильности конкатенации запросов (например, с помощью присвоений переменных с извлечением данных в конкретный заказ). Выход запроса может измениться в SQL Server 2008 в зависимости от выбора плана, данных в таблицах и т.д. Вы не должны полагайтесь на это, работая последовательно, хотя синтаксис позволяет вам написать инструкцию SELECT, которая смешивает упорядоченное упорядочение строк с помощью назначение переменной.
Поведение, которое вы видите, - это дизайн. Использование операций присваивания (конкатенация в этом примере) в запросах с предложением ORDER BY имеет undefined. Это может измениться с момента выпуска до выпуска или даже в пределах определенной версии сервера из-за изменений в плане запроса. Вы не можете полагаться на это поведение, даже если есть обходные пути. Видеть ниже статья KB для более подробной информации:
http://support.microsoft.com/kb/287515 ТОЛЬКО гарантировано механизм:
- Используйте курсор для прокрутки строк в определенном порядке и объединения значений
- Использовать для запроса xml с ORDER BY для генерации конкатенированных значений
- Использовать агрегат CLR (это не будет работать с предложением ORDER BY)
Поведение, которое вы видите, на самом деле по дизайну. Это связано с SQL является языком манипуляции множеством. Все выражения в SELECT список (и это включает в себя также задания), не гарантируется выполняется ровно один раз для каждой выходной строки. Фактически, SQL-запрос Оптимизатор пытается выполнить их как можно меньше. Эта даст ожидаемые результаты, когда вы вычисляете значение переменная, основанная на некоторых данных в таблицах, но когда значение, которое вы назначаются, зависит от предыдущего значения той же переменной, результаты могут быть довольно неожиданными. Если оптимизатор запросов перемещает выражение в другое место в дереве запросов, оно может получить оценивается меньше времени (или только один раз, как в одном из ваших примеров). Эта поэтому мы не рекомендуем использовать назначения типа "итерация" для вычислить совокупные значения. Мы обнаруживаем, что обходные методы на основе XML... обычно хорошо работают для клиенты
Даже без ORDER BY мы не гарантируем, что @var = @var + будет производить конкатенированное значение для любого заявления который влияет на несколько строк. Правая часть выражения может оцениваться один или несколько раз во время выполнения запроса и поведение, как я сказал, зависит от плана.
Назначение переменной с помощью оператора SELECT является проприетарным синтаксисом (Только для T-SQL), где поведение undefined или зависит от плана, если создается несколько строк. Если вам нужно выполнить конкатенацию строк затем используйте компиляцию SQLCLR или FOR XML на основе конкатенации или другие реляционные методы.