J.D*_*.D. 5 sql-server order-by determinism functions sql-server-2017
我需要拆分一个逗号分隔的字符串,对其进行操作,然后将其连接回一个保留数据原始顺序的字符串(如果可能)。
例如,采用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子句,从 a Tableor等数据集中选择时不能保证排序View,但想知道函数是否有区别?
当我输入这个时,我有一种预感,答案是否定的,排序不是确定性的,因此我不能保证结果的顺序。此外,我打赌可能会为我在结果之上运行的每个函数添加额外的不确定性,尤其是当我将它们与STRING_AGG(). (不管答案如何,我感谢您的帮助,你们都是很酷的数据人员。;)
Aar*_*and 11
不,它们不是以确定的顺序返回。
虽然您不太可能看到它们以不同的顺序返回,但这并不能使当前行为具有确定性或可靠性。ROW_NUMBER() OVER (ORDER BY (SELECT 1))类似在 CTE 等中间位置应用到输出的技巧同样不能保证有效。
这是 中明显缺少的功能之一STRING_SPLIT(),我已经在博客中介绍过:
Andy Mallon 也是如此:
在这里投票和评论:
(该项目特别要求返回一个额外的列以指示原始字符串中的位置,但由于向后兼容性问题,可能需要通过一个新函数来传递,类似于原来的CONCAT_WS方式。)
顺便说一句,文档最初指出:
输出行的排序顺序与输入字符串中子字符串的顺序相匹配。
在这次提交中故意改变了这一点,以消除任何承诺退货单的概念。现在文档指出:
输出行可以按任何顺序排列。该顺序不能保证与输入字符串中子字符串的顺序匹配。
为什么他们需要取消那个承诺?
我不熟悉内部实现,但我相信文档的原始版本是由观察者编写的,而不是函数作者。该声明可能是这样编写的,因为这是他们在使用该函数时观察到的行为。当我们告诉人们ORDER BY从聚簇表中选择行时我们不需要这些行时,我们中的许多人都会做同样的事情:“它们将始终按此顺序出现。” 非常可靠,直到优化器选择不同的索引。
我的猜测是他们正在为未来的行为遮掩自己的屁股。想想他们对函数的工作方式所做的所有更改,以及对优化器的持续更改。
目前,在简单的情况下:
SELECT * FROM STRING_SPLIT('cow,dog,dinosaur','');
Run Code Online (Sandbox Code Playgroud)
除了顺序之外,没有太多机会或理由。但是,当您OUTER APPLY针对nvarchar(max)两个巨大的分区表之间的列,并且数据开始以批处理模式和/或并行方式处理时呢?他们是否必须在代码中编写额外的逻辑以确保所有输出都以正确的顺序返回?值得吗?他们是否必须在未来每次功能处理/优化器更改时重新访问它以保持该承诺?
| 归档时间: |
|
| 查看次数: |
303 次 |
| 最近记录: |