ORDER BY(SELECT NULL)

时间:2017-09-20 12:15:23

标签: sql sql-server

我们使用一个小的sql函数,它通过某个分隔符拆分字符串并在表中返回这些值。

ALTER FUNCTION [shark].[SplitStrings]
(
   @List      VARCHAR(MAX),
   @Delimiter VARCHAR(255)
)
RETURNS TABLE
AS
  RETURN ( SELECT [Item], ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS [Id] FROM
      ( SELECT Item = x.i.value('(./text())[1]', 'varchar(max)')
        FROM ( SELECT [XML] = CONVERT(XML, '<i>'
        + REPLACE(@List, @Delimiter, '</i><i>') + '</i>').query('.')
          ) AS a CROSS APPLY [XML].nodes('i') AS x(i) ) AS y
      WHERE Item IS NOT NULL
  );

问题是,这是否可以改变字符串中元素的顺序?

实施例。

 SELECT * FROM [shark].[SplitStrings] ('1,2,3,4,5', ',')

可以返回

1
5
3
4
2 

而不是

1
2
3
4
5 

更多信息: 经过几个月的正常工作,我们发现我们的一个组件中的一个错误,我们可以找到的唯一来源,可能导致此错误的是上述过程。它以某种方式改变了包含65 000个元素的字符串数组的顺序(带分隔符的字符串的总长度为65 000 * 11)。我们试图在同一个SQL服务器上重现相同的错误,但没有任何运气。你的评论和回答让这个蠢货更加内疚。

2 个答案:

答案 0 :(得分:1)

通常,select语句将始终返回未排序的结果集。所以你问的一般答案是:是的,你的select语句可以返回任何元素的顺序。这将确认SQL标准。 (最好不要相信任何其他事情。)

但是:你在你的函数中放了一个隐含的顺序。此顺序由XML-Fragment中的-elements顺序生成。此XML按照您构造转换为XML的字符串的顺序进行处理。这被用作交叉申请的右侧(您不能使用此处并且不需要任何订单)。因此,您的问题的答案是:不,您的select语句将始终返回给定的元素顺序。

答案 1 :(得分:1)

更多信息,不适合评论:

该问题的最小陈述类似于

SELECT x.i.value('(./text())[1]', 'varchar(100)') as Item
FROM 
   (SELECT CONVERT(XML, '<i>1</i><i>2</i>') as [XML]) AS a 
CROSS APPLY [XML].nodes('i') AS x(i);

问题归结为:结果可能按此顺序排列吗?

2
1 

此查询的执行计划如下所示:

|--Compute Scalar(DEFINE:([Expr1011]=[Expr1010]))
   |--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1000], XML Reader with XPath filter.[id]))
        |--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1000]))
        |    |--Constant Scan(VALUES:((CONVERT(xml,'<i>1</i><i>2</i>',0))))
        |    |--Filter(WHERE:(STARTUP EXPR([Expr1000] IS NOT NULL)))
        |         |--Table-valued function
        |--Stream Aggregate(DEFINE:([Expr1010]=MIN(CASE WHEN [Expr1000] IS NULL THEN NULL ELSE CASE WHEN datalength(XML Reader with XPath filter.[value])>=(128) THEN CONVERT_IMPLICIT(varchar(100),XML Reader with XPath filter.[lvalue],0) ELSE CONVERT_IMPLICIT(varchar(100),XML Reader with XPath filter.[value],0) END END)))
             |--Top(TOP EXPRESSION:((1)))
                  |--Compute Scalar(DEFINE:([Expr1009]=0x58))
                       |--Filter(WHERE:(XML Reader with XPath filter.[id]=getancestor(XML Reader with XPath filter.[id],(1))))
                            |--Table-valued function

也许有理由使用来自XML Reader的数据对嵌套循环中的元素进行排序,但这不确定,也没有关于此的文档。

甚至没有找到关于这个问题的文档:如何在不改变XML结构的情况下正确保持排序(即在XML中添加排序键)?