在 SQL Server 2019 中对函数使用 @@rowcount 时出现问题

Problem when using @@rowcount on function in SQL Server 2019

我在这样的函数中使用 @@rowcount

ALTER FUNCTION [dbo].[GetUserNameFamily] 
    (@UsrID INT)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    DECLARE @Name NVARCHAR(MAX)
    DECLARE @Family NVARCHAR (MAX)
    DECLARE @cou INT
    
    SELECT @Name = ut.Fname, @Family = ut.Lname
    FROM User_tbl ut 
    WHERE ut.UserID = @UsrID

    IF @@ROWCOUNT = 0
        RETURN 'row 0'

    IF @Name IS NULL
        SET @Name = ''

    IF @Family IS NULL  
        SET @Family = ''

    RETURN @Name + ' ' + @Family    
END

当我在这样的查询中使用这个函数时:

declare @ID int=3118

select * 
from Files_tbl 
where RefID = @ID    -- query rows affected is 0
    
select 
    dbo.GetUserNameFamily(TicketResponse_tbl.CreateByUserID) as CreateByFullName
from 
    TicketResponse_tbl
where 
    TicketResponse_tbl.TicketID = @ID

我的结果是:

删除 where in "select Files_tbl" 查询并将此查询受影响的行从 0 更改为 n。

declare @ID int = 3118

select * 
from Files_tbl 
-- where RefID = @ID  -- query rows affected is not 0
    
select 
    dbo.GetUserNameFamily(TicketResponse_tbl.CreateByUserID) as CreateByFullName
from 
    TicketResponse_tbl
where 
    TicketResponse_tbl.TicketID = @ID

我的函数结果更改为:

将数据库兼容级别升级到 SQL Server 2019

后出现此问题

正如其他人所提到的,was a bug 在名为 Scalar UDF Inlining 的新(2019)功能中涉及 side-affecting 函数,例如 @@ROWCOUNT.更新到最新版本的 SQL 服务器(无论如何你都应该这样做)会解决这个问题。


尽管如此,要继续使用内联,您可以通过像这样简化函数来避免 @@ROWCOUNT

CREATE OR ALTER FUNCTION [dbo].[GetUserNameFamily] 
    (@UsrID INT)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    RETURN ISNULL((
        SELECT CONCAT(ut.Fname, ' ', ut.Lname)
        FROM User_tbl ut 
        WHERE ut.UserID = @UsrID
    ), 'row 0');
END

但我建议您将其转换为内联 Table 值函数,它将始终被内联:

CREATE OR ALTER FUNCTION [dbo].[GetUserNameFamily] 
    (@UsrID INT)
RETURNS TABLE
AS RETURN

SELECT
  ISNULL((
        SELECT CONCAT(ut.Fname, ' ', ut.Lname)
        FROM User_tbl ut 
        WHERE ut.UserID = @UsrID
    ), 'row 0') AS UserName;

你这样用

SELECT n.UserName
FROM YourTable t
CROSS APPLY dbo.GetUserNameFamily(t.Id) n;