2 回答

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