在 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;
我在这样的函数中使用 @@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;