2 回答

TA貢獻1946條經驗 獲得超4個贊
未定義聚合連接查詢的正確行為。
為了實現聚合連接查詢的預期結果,請將任何Transact-SQL函數或表達式應用于SELECT列表中的列,而不是ORDERBY子句中的列。
ORDER BY
出于向后兼容性的原因,SQLServer提供了對SELECT@p=@p+1類型賦值的支持.在最高的范圍內訂購。
[Expr1003] = Scalar Operator([@x]+[Expr1004])
@x = @x + [msg]
@x
我們不保證連接查詢的正確性(比如使用變量賦值和特定順序的數據檢索)。SQL Server 2008中的查詢輸出可以根據計劃選擇、表中的數據等進行更改。即使語法允許您編寫一個SELECT語句,將有序的行檢索與變量賦值混合在一起,您也不應該一直依賴這種工作。
你所看到的行為是故意的。在帶有ORDERBY子句的查詢中使用賦值操作(在本例中為串聯)具有未定義的行為。由于查詢計劃的更改,這可能在不同版本之間發生更改,甚至在特定的服務器版本中也會發生變化。即使有解決辦法,也不能依賴這種行為。有關更多細節,請參見下面的KB文章: http://support.microsoft.com/kb/287515 唯一的保障機制如下:
使用游標按特定順序遍歷行,并將值連接起來。 用于帶有Orderby的xml查詢,以生成級聯的值 使用CLR聚合(這不適用于ORDERBY子句)
你所看到的行為實際上是故意的。這與SQL是一種集操作語言有關。SELECT列表中的所有表達式(這也包括賦值)不能保證對每個輸出行精確執行一次。實際上,SQL查詢優化器試圖盡可能少地執行它們。當您根據表中的某些數據計算變量的值時,這將給出預期的結果,但是當您要分配的值取決于同一變量的前一個值時,結果可能是非常出乎意料的。如果查詢優化器將表達式移動到查詢樹中的不同位置,則可能會得到較少的計算次數(或者只得到一次,如您的一個示例所示)。這就是為什么我們不建議使用“迭代”類型賦值來計算聚合值的原因。我們發現基于XML的解決方案.通常為客戶服務。
即使沒有ORDERBY,我們也不能保證@var=@var+將為任何影響多行的語句生成級聯值。表達式的右側可以在查詢執行期間計算一次或多次,而且正如我所說的行為依賴于計劃。
帶有SELECT語句的變量賦值是一種專有語法(僅為T-SQL),在這種語法中,行為是未定義的,如果產生多個行,則計劃依賴。如果需要進行字符串連接,則使用SQLCLR聚合或用于基于XML查詢的連接或其他關系方法。
添加回答
舉報