PREMISE :无法更改应用程序代码。条件非常具体。我正在寻找书籍上的东西,如果可能的话,这是最后的解决方法。
我有一个表值函数(内联),可生成2到7条记录。有时它可能只有1或最多15(但很少)。
该函数仅以这种方式由应用程序使用,没有任何ORDER BY。
select * from dbo.myfunction(...)
根据您的经验,是否有任何方式保证确保(根据您使用特定技术观察到的)第二列按顺序返回结果?列是:varchar(3),datetime,varchar(50)。
不要让我开始选择* ,它是 INTENTIONAL ,这样前端会显示很多列,我将来会显示该功能。
根据经验,使用单个索引(群集PK)来遍历数据,任何当前版本的SQL Server和SP级别都应始终对< 20条记录执行简单的INDEX SCAN而不进行并行操作,从而让我订购导致应用程序选择。
你的想法?我更愿意将理论排除在讨论之外。如果你能坚持实践经验并在家里继续讲述最佳实践,我也会很感激。
已更新 这就是现在的样子
create function dbo.myfunction(....)
returns @RES table
(
[#] int identity primary key clustered,
[Varchar3Col] varchar(3),
[DateTimeCol] datetime,
[Varchar50Col] varchar(50)
) as
BEGIN
declare @RES2 table
(
rn int,
[Varchar3Col] varchar(3),
[DateTimeCol] datetime,
[Varchar50Col] varchar(50)
)
insert @RES2
select rn=row_number() over (order by action_time),
[Varchar3Col]
[DateTimeCol]
[Varchar50Col]
from (.....)
inner join (.....) ON (.....)
declare @i int
set @i = 0
while @@rowcount > 0 begin
set @i=@i+1
insert @RES
select [Varchar3Col], [DateTimeCol], [Varchar50Col]
from @RES2
where rn=@i
end
return
END
GO
这是否有效(使用来自应用程序层的直接SELECT)?
答案 0 :(得分:7)
对于内联TVF,没有什么能真正起作用。不仅如此,内联TVF甚至可以返回更多行,而不是你认为应该这样做的行,并且在执行TVF之后将修剪行(基本上是TVF定义中的谓词)可以从TVF中拉出并移动到查询树中的其他位置)。有关此情况的示例,请参阅T-SQL functions do no imply a certain order of execution。
将内联TVF转换为多语句将引入一些程序顺序,因为语句不能无序执行,但TVF结果可能会被重新排序,排序,拆分,假脱机,基本上由生成的优化器损坏计划,最终打破你对输出订单的假设。我担心如果你必须有一定的执行顺序,那么游标就是你最好的朋友。
答案 1 :(得分:2)
只是你不喜欢你听到的答案吗?事实是,订单只能通过order by子句得到保证。这不是意见,而是事实。如果它是您正在寻找的保证,则别无选择。
答案 2 :(得分:-1)
如果只有一个应用程序正在使用该函数,那么就像你提到的那样(因此没有加入/应用于另一个对象),这应该是一个特色! 将oder by子句添加到数据返回查询以按特定顺序接收结果集。
总是有风险你的fn将被另一个开发者使用,但不会像你想要的那样被使用,造成各种问题。表演是我会担心的。
答案 3 :(得分:-3)
如果您使用单一语句TVF而不是多语句TVF,您可以更好地了解可预测的查询计划。 ROW_NUMBER OVER应该在RES2查询中提供您想要的顺序,如果没有,只需将其放入CTE并按行号列排序。见下文。
CREATE FUNCTION [dbo].[MyFunction]
(
/*
Parameters
*/
)
RETURNS TABLE
RETURN
WITH res2
(
rn,
Varchar3Col,
DateTimeCol,
Varchar50Col
)
AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY action_time) AS rn,
Varchar3Col,
action_time AS DateTimeCol,
Varchar50Col
FROM
/*
[...from statement...]
*/
)
SELECT
rn,
Varchar3Col,
DateTimeCol,
Varchar50Col
FROM
res2
ORDER BY
rn;