Sql server 函数调用了多少次
让我们进行以下查询:Sql server 函数调用了多少次,sql-server,Sql Server,让我们进行以下查询: SELECT * FROM {tablename} WHERE ColumnId = dbo.GetId() 其中dbo.GetId()是非确定性的用户定义函数。问题是对整个查询只调用一次dbo.GetId(),然后应用其结果,还是对每一行调用它?我认为每一行都需要这样做,但我不知道如何证明这一点 下面的查询是否会更有效 DECLARE @Id int SET @Id = dbo.GetId() SELECT * FROM {tablename} WHERE Column
SELECT * FROM {tablename} WHERE ColumnId = dbo.GetId()
其中dbo.GetId()是非确定性的用户定义函数。问题是对整个查询只调用一次dbo.GetId(),然后应用其结果,还是对每一行调用它?我认为每一行都需要这样做,但我不知道如何证明这一点
下面的查询是否会更有效
DECLARE @Id int
SET @Id = dbo.GetId()
SELECT * FROM {tablename} WHERE ColumnId = @Id
是的,它确实每行被调用一次。 有关调试函数,请参见以下线程 是的,下面的查询是有效的,因为函数只调用一次
DECLARE @Id int
SET @Id = dbo.GetId()
SELECT * FROM {tablename} WHERE ColumnId = @Id
这里有一种方法可以证明这一点 看法 创建视图是为了在
用户定义函数中添加非确定性
内置函数
CREATE VIEW vw_rand
AS
SELECT Rand() ran
不确定函数
现在使用上面的视图创建一个不确定的用户定义函数
CREATE FUNCTION Udf_non_deterministic ()
RETURNS FLOAT
AS
BEGIN
RETURN
(SELECT ran
FROM vw_rand)
END
样本表
CREATE TABLE #test
(
id INT,
name VARCHAR(50)
)
INSERT #test
VALUES (1,'a'),
(2,'b'),
(3,'c'),
(4,'d')
SELECT dbo.Udf_non_deterministic (), *
FROM #test
结果:
id name non_deterministic_val
1 a 0.203123494465542
2 b 0.888439497446073
3 c 0.633749721616085
4 d 0.104620204364744
正如您可以看到的,对于所有的行,函数都被调用了我怀疑在任何地方都不能保证这一点。如果要确保它,请使用变量 我修改了@Prdp的例子
CREATE VIEW vw_rand
AS
SELECT Rand() ran
GO
/*Return 0 or 1 with 50% probability*/
CREATE FUNCTION dbo.Udf_non_deterministic ()
RETURNS INT
AS
BEGIN
RETURN
(SELECT CAST(10000 * ran AS INT) % 2
FROM vw_rand)
END
go
SELECT *
FROM master..spt_values
WHERE dbo.Udf_non_deterministic() = 1
在这种情况下,它只评估一次。返回所有行或零
原因是该计划有一个带有启动谓词的筛选器
启动表达式谓词是[tempdb].[dbo].[Udf\u non\u deterministic]()=(1)
当打开筛选器以查看是否从子树中获取行时,这只会计算一次,而不是针对通过它的每一行
但反过来,下面的表达式每次返回的行数不同,表明它是按行计算的。与列的比较可防止在过滤器中预先对其求值,如前一示例所示
SELECT *
FROM master..spt_values
WHERE dbo.Udf_non_deterministic() = (number - number)
这个重写回到了一次评估(对我来说),但是交叉应用
仍然给出了多个评估
SELECT *
FROM master..spt_values
OUTER APPLY(SELECT dbo.Udf_non_deterministic() ) AS C(X)
WHERE X = (number - number)
在函数中增加一个特定值(表行中的int值),您就会知道。答案是yes和yes。因为无法知道dbo.GetId()中预期的输出函数,因此它每行执行一个函数。@dotNET-这将是一个令人印象深刻的成就,因为DML在函数中是被禁止的。您在这里的具体要求是什么?您是否在寻找某种形式的担保,如果是,是什么形式的担保?每行至少调用一次、最多调用一次、恰好调用一次?
PRINT
在函数中是一个副作用运算符,因此它不允许您在函数中使用PRINT
。感谢您提供的信息。:)我将保留我的答案,只是作为你答案中的参考