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
。感谢您提供的信息。:)我将保留我的答案,只是作为你答案中的参考