STRING_SPLIT() 函式的結果是否以確定的順序返回?
我需要拆分以逗號分隔的字元串,對其進行操作,然後將其連接回單個字元串,保留數據的原始順序(如果可能)。
例如,採用這樣的
CREATE TABLE
語句(作為字元串)的列定義列表'BrentOzarColumn INTEGER, PaulWhiteColumn DATETIME, ErikDarlingColumn VARCHAR(100)'
。我想將逗號分隔的列表拆分為一個結果集,例如使用 SQL Server 的內置函式,如下所示STRING_SPLIT()
:SELECT TRIM([Value]) AS CoolDataPeople FROM STRING_SPLIT('BrentOzarColumn INTEGER, PaulWhiteColumn DATETIME, ErikDarlingColumn VARCHAR(100)', ',')
在不指定
ORDER BY
子句的情況下,這會重複產生(通過巧合?)以下結果,這些結果似乎按照與字元串中相同的順序進行排序:一旦我得到了上面的結果集,我想對每一行應用一些額外的字元串操作(比如附加一些常量文本),然後用一個函式連接每一行,比如
STRING_AGG()
(再見天數STUFF ... FOR XML PATH
:),順序與原始字元串。所以我的最終結果的一個例子可能是'BrentOzarColumn INTEGER SQLROX, PaulWhiteColumn DATETIME SQLROX, ErikDarlingColumn VARCHAR(100) SQLROX'
.最終我的問題是:函式**的結果是否
STRING_SPLIT()
以確定的順序返回?**我知道沒有ORDER BY
子句,從 aTable
or之類的數據集中選擇時不能保證排序View
,但想知道函式是否有區別?當我輸入這個時,我有一種預感,答案是否定的,排序不是確定性的,因此我不能保證結果的順序。此外,我敢打賭,我在結果之上執行的每個函式都可能添加了額外的不確定性,尤其是當我將它們與
STRING_AGG()
. (無論答案如何,我都感謝您的幫助,你們都是很酷的數據人。;)
不,它們不是按確定的順序返回的。
雖然您不太可能看到它們以不同的順序返回,但這並不能使目前行為具有確定性或可靠性。
ROW_NUMBER() OVER (ORDER BY (SELECT 1))
類似在 CTE 等中間位置應用到輸出的技巧同樣不能保證有效。
STRING_SPLIT()
這是我在部落格中提到的明顯缺失的功能之一:Andy Mallon 也是如此:
在這裡投票和評論:
(該項目特別要求返回一個額外的列來指示原始字元串中的位置,但由於向後兼容性問題,可能需要通過一個新函式來傳遞,類似於如何
CONCAT_WS
出現。)順便說一句,文件最初指出:
輸出行的排序順序與輸入字元串中子字元串的順序相匹配。
在此送出中故意更改了這一點,以消除任何承諾退貨訂單的概念。現在文件指出:
輸出行可以是任何順序。不保證順序與輸入字元串中子字元串的順序相匹配。
為什麼他們需要取消這個承諾?
我不熟悉內部實現,但我相信文件的原始版本是由觀察者編寫的,而不是函式作者。該語句可能是這樣寫的,因為這是他們在使用該函式時觀察到的行為。當我們告訴人們從聚群表中選擇行時我們不需要
ORDER BY
時,我們中的許多人都會做同樣的事情:“它們總是按這個順序出來的。” 非常可靠,直到優化器選擇不同的索引。我的猜測是他們正在為未來的行為掩蓋他們的屁股。想想他們對函式工作方式所做的所有更改,以及對優化器的持續更改。
目前,使用簡單的案例:
SELECT * FROM STRING_SPLIT('cow,dog,dinosaur','');
除了順序之外,沒有太多機會或理由。但是,當您
OUTER APPLY
針對nvarchar(max)
兩個巨大的分區表之間的列,並且數據開始以批處理模式和/或併行處理時呢?他們是否必須在程式碼中編寫額外的邏輯以確保所有輸出以正確的順序返回?值得嗎?他們是否必須為將來的每個功能處理/優化器更改重新訪問它以保持該承諾?他們正在做出哪些改變?
該文件最近已更新,以顯示函式的新參數
enable_ordinal
,可在 Azure SQL 數據庫中使用,並且即將在 SQL Server 2022 中推出:enable_ordinal
一個 int 或位表達式,用作啟用或禁用序數輸出列的標誌。值 1 啟用序數列。如果省略 enable_ordinal、NULL 或值為 0,則禁用序號列。
注意
enable_ordinal 參數和序號輸出列目前僅在 Azure SQL 數據庫、Azure SQL 託管實例和 Azure Synapse Analytics(僅限無伺服器 SQL 池)中受支持。
需要明確的是,添加此參數只會
ordinal
在輸出中添加一列,指示value
原始字元串中的序列;它仍然不能保證輸出將按列**排序ordinal
。為此,您仍然需要添加ORDER BY
到輸出中。