Различный вывод при выполнении оператора напрямую и из хранимой процедуры? - PullRequest
1 голос
/ 04 апреля 2011

Sql Server 2008 ведет себя странным образом. Когда я выполняю хранимую процедуру, выход будет в другом порядке, чем когда я выполняю операторы непосредственно для тех же параметров. Я не уверен, что я делаю неправильно. Пожалуйста, помогите !!!

Вот простая структура запроса и объясните, что он делает.

Top 10 Query1
Union all
Top 10 Query2
Order by name

а. Когда вы запускаете его в proc: Из запроса 1 он выбирает топ-10, затем из запроса 2 он выбирает топ-10 и, наконец, выполняет порядок

б. Когда вы открываете запрос: Из запроса 1 он применяет порядок и затем выбирает первые 10, а из запроса 2 он также применяет порядок и затем выбирает первые 10

Странно, что он делает 2 разные вещи с одним и тем же запросом.

Output from Procedure
Name                                          Cost Price
A2 Bag Stickerss DO NOT STOCKTAKES               24
aaaaaa                                           5
aaaaaa                                           7.5


Output from Query
Name                                          Cost Price
A2 Bag Stickerss DO NOT STOCKTAKES               24
A2 Bag Stickerss DO NOT STOCKTAKES               27
aaaaaa                                           5
aaaaaa                                           7.5
aaaaaa                                           9

1 Ответ

4 голосов
/ 05 апреля 2011

TOP без ORDER BY не является детерминированным.

Это просто означает «Выбрать любые 10 записей».Таким образом, вы выбираете произвольный набор из 10 результатов из запроса 1 и произвольный набор из 10 записей из запроса 2, а затем упорядочиваете эти 20 записей по имени.

Какой TOP 10 в итоге вы получите, зависит от выбранного плана(что может отличаться в хранимой процедуре) Вам необходимо добавить порядок (для набора столбцов без связей) к каждому запросу, чтобы сделать его детерминированным.

Ваш текущий запрос похож на

SELECT TOP 10 * 
FROM master..spt_values
UNION ALL
SELECT TOP 10 * 
FROM master..spt_values
ORDER BY name

Plan 1

Вы видите, что SQL Server просто добавляет итератор TOP в обе ветви плана, чтобы ограничитьвывод обоих запросов, затем они поступают в Союз, и после этого происходит сортировка по имени.Для этого SQL Server выбрал сканирование кластеризованного индекса, поэтому результаты, скорее всего, будут ТОП-10 в порядке кластеризованного индекса type,number,name (хотя на это не следует полагаться и без указанного порядка, чтобы указать, к чему относится TOP любой набор из 10 строк будет действительным. Было бы совершенно правильно использовать здесь функцию расширенного сканирования и дать вам произвольные 10 строк, которые, как он знает, находятся в кэше какони были только что прочитаны при сканировании другого запроса.)

Чтобы переписать запрос с TOP...ORDER BY, указанным для каждого элемента, вы можете использовать CTE, как показано ниже.

;WITH Query1 AS
(
SELECT TOP 10 * 
FROM master..spt_values
ORDER BY name,number,type
), Query2 AS
(
SELECT TOP 10 * 
FROM master..spt_values
ORDER BY number,type,name
)

SELECT * 
FROM Query1
UNION ALL
SELECT * 
FROM Query2
ORDER BY name

Plan 2

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...