[英]Table-Valued function - Order by is ignored in output
我们正在从SQL Server 2008迁移到SQL Server 2012,并立即注意到我们所有的表值函数都不再以正确排序的顺序提供临时表内容。
码:
INSERT INTO @Customer
SELECT Customer_ID, Name,
CASE
WHEN Expiry_Date < GETDATE() then 1
WHEN Expired = 1 then 1
ELSE 0
END
from Customer **order by Name**
在SQL Server 2008中,此函数返回按名称排序的客户。 在SQL Server 2012中,它返回未排序的表。 SQL 2012中忽略了“order by” 。
我们是否必须重新编写所有函数以包含sort_id
,然后在主应用程序中调用它们时对它们进行排序还是有一个简单的修复方法?
你的原始方法有两个问题。
ORDER BY
的INSERT ... SELECT ... ORDER BY
将是该行实际上是插入的顺序。 ORDER BY
SELECT
将以任何特定顺序返回行,例如插入顺序。 在2012年,看起来行为已经相对于第1项发生了变化。它现在通常忽略SELECT
语句上的ORDER BY
,它是INSERT
的来源
DECLARE @T TABLE(number int)
INSERT INTO @T
SELECT number
FROM master..spt_values
ORDER BY name
更改行为的原因是,在以前的版本中,SQL Server生成了一个在SET ROWCOUNT 0
(关闭)和SET ROWCOUNT N
执行之间共享的计划。 排序运算符仅用于确保计划由具有非零ROWCOUNT
集的会话运行时的正确语义。 左边的TOP
运算符是ROWCOUNT TOP
。
SQL Server 2012现在为这两种情况生成单独的计划,因此无需将这些计划添加到计划的ROWCOUNT 0
版本中。
如果SELECT
具有明确的TOP
定义(除了TOP 100 PERCENT
),那么排序可能仍会出现在2012年的计划中,但这仍然不能保证行的实际插入顺序,那么计划可能在TOP N
之后有另一种排序例如,建立将行引入聚簇索引顺序。
对于您问题中的示例,我只需调整调用代码以指定ORDER BY name
如果这是它所需要的。
关于来自SQL Server中的Ordering保证的 sort_id
想法,当使用IDENTITY
插入表时,保证按顺序分配这些订单将按照ORDER BY
所以你也可以这样做
DECLARE @Customer TABLE (
Sort_Id INT IDENTITY PRIMARY KEY,
Customer_ID INT,
Name INT,
Expired BIT )
INSERT INTO @Customer
SELECT Customer_ID,
Name,
CASE
WHEN Expiry_Date < Getdate() THEN 1
WHEN Expired = 1 THEN 1
ELSE 0
END
FROM Customer
ORDER BY Name
但是你仍然需要在你选择的查询中通过sort_id
进行排序,因为没有那个没有保证的顺序(也许这种sort_id
方法在用于排序的原始列没有被复制到表变量的情况下可能是有用的)
将名为rowno的列添加到@Customer表
INSERT INTO @Customer
SELECT ROW_NUMBER()over(order by Name)rowno,Customer_ID, Name,
CASE
WHEN Expiry_Date < GETDATE() then 1
WHEN Expired = 1 then 1
ELSE 0
END
from Customer
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.