SELECT 賦值與ORDER BY沖突的問題_Mssql數據庫教程
推薦:SqlServer2005對現有數據進行分區具體步驟RegMail是用來存放注冊郵件的表,現以創建時間(CreateTime)字段來給表進行分區,具體步驟如下: --為分區創建存儲文件 ALTER DATABASE Test ADD FILEGROUP RegMailFile2007 ALTER DATAB
問題描述:
使用 SELECT 語句,輪詢表中的數據,并且處理變量數據時,如果有ORDER BY語句,則得不到想要的結果,但去掉ORDER BY,結果正常。
具體的問題表現參考下面的問題重現代碼
問題重現代碼
-- 測試數據
DECLARE @T TABLE(id int,value nvarchar(16))
INSERT INTO @T SELECT
1, N'好人' UNION ALL SELECT
2, N'壞人' UNION ALL SELECT
3, N'吃飯' UNION ALL SELECT
4, N'垃圾'
-- 賦值處理
DECLARE @str nvarchar(4000)
SET @str = N'我不是一個好人,也不是垃圾'
SELECT @str = REPLACE(@str, value, N'<u>' value N'</u>')
FROM @T
WHERE CHARINDEX(value, @str) > 0
--ORDER BY CHARINDEX(value, @str) DESC
SELECT @str
/* -- 結果(當賦值處理語句注釋掉ORDER BY 時)
我不是一個<u>好人</u>,也不是<u>垃圾</u>
-- */
/* -- 結果(當賦值處理語句加上ORDER BY 時)
我不是一個<u>好人</u>,也不是垃圾
-- */
問題分析:
兩個處理語句的結果不同,通過查看它們的執行計劃應該可以看出原因所在,為此,通過
SET SHOWPLAN_ALL ON
輸出了兩種執行語句的執行計劃(僅StmtText部分,有興趣的讀者在自己的電腦上測試的時候,可以去了解其他部分的信息)
從上面的列表可以看出,兩種處理的最大差異,在于賦值前,是否有ORDER BY 子句,從一般的理解上,可能會認為是否排序并不重要,但換個角度來看問題,就比較容易理解為什么有ORDER BY子句后得不到我們想要的結果了:
當有ORDER BY子句時,對于SELECT @str = 這種賦值處理,SQL Server認為賦值處理肯定只會保留最后一條記錄的處理結果,而ORDER BY子句確定了數據順序,也就知道最后一條記錄是那個,因此只會處理ORDER BY的最后一條記錄。(讀者可以自行去測試一下,調整ORDER BY順序,看看結果是否與我的推論相符)
當沒有ORDER BY子句時,因為無法確定數據順序,所以SQL Server必須掃描滿足條件的每條數據來得到結果,這樣每掃描一條記錄都會處理一次,所以結果是我們所預知的
問題解決方法:
修改處理語句,使查詢優化器使用與我們需要結果一致的執行方法,可以解決這個問題。
對于示例中的處理語句,可以調整如下:
DECLARE @str nvarchar(4000)
SET @str = N'我不是一個好人,也不是垃圾'
SELECT @str = REPLACE(@str, value, N'<u>' value N'</u>')
FROM(
SELECT TOP 100 PERCENT
value
FROM @T
WHERE CHARINDEX(value, @str) > 0
ORDER BY CHARINDEX(value, @str) DESC
)A
SELECT @str
補充:
此問題的結論只是筆者對于查詢分析的一個推論,并無相應的官方文檔可以證明,所以歡迎大家發表自己的看法
分享:講解數據庫調優與程序員相關的幾個方面許多程序員在面試時,經常會被問到 “數據庫調優”的事情,這時,許多人就會產生疑問,這不是DBA的事嗎,但回答不好還是顯得不夠專業,筆者查找了一些相關資料,發現許多方面還真是程
- sql 語句練習與答案
- 深入C++ string.find()函數的用法總結
- SQL Server中刪除重復數據的幾個方法
- sql刪除重復數據的詳細方法
- SQL SERVER 2000安裝教程圖文詳解
- 使用sql server management studio 2008 無法查看數據庫,提示 無法為該請求檢索數據 錯誤916解決方法
- SQLServer日志清空語句(sql2000,sql2005,sql2008)
- Sql Server 2008完全卸載方法(其他版本類似)
- sql server 2008 不允許保存更改,您所做的更改要求刪除并重新創建以下表
- SQL Server 2008 清空刪除日志文件(瞬間日志變幾M)
- Win7系統安裝MySQL5.5.21圖解教程
- 將DataTable作為存儲過程參數的用法實例詳解
- 相關鏈接:
- 教程說明:
Mssql數據庫教程-SELECT 賦值與ORDER BY沖突的問題
。