SQL Server函数返回意外结果

时间:2016-11-24 16:22:25

标签: sql sql-server function

我有一个函数来检查用户是否经过身份验证但结果不正确:

CREATE FUNCTION [dbo].[IsAuthorized] 
    (@UserToken nvarchar(250), 
     @UserCode nvarchar(250))
RETURNS int
AS
BEGIN
    IF (SELECT [User].UserId 
        FROM [User] 
        INNER JOIN UserLogin ON [User].UserId = UserLogin.UserId 
        WHERE [User].UserCode = @UserCode 
          AND UserLogin.UserToken = @UserToken 
          AND UserLogin.UserTokenExpiration > GETDATE()) > 0
        RETURN 1;

    IF NOT EXISTS (SELECT [User].UserId 
                   FROM [User] 
                   WHERE [User].UserCode = @UserCode)
        RETURN -201;    -- User does not exist

    IF NOT EXISTS (SELECT [User].UserId 
                   FROM [User] 
                   INNER JOIN UserLogin ON [User].UserId = UserLogin.UserId 
                   WHERE [User].UserCode = @UserCode 
                     AND UserLogin.UserToken = @UserToken)
        RETURN -202;    -- Token is not valid

    IF EXISTS (SELECT [User].UserId 
               FROM [User] 
               INNER JOIN UserLogin ON [User].UserId = UserLogin.UserId 
               WHERE [User].UserCode = @UserCode 
                 AND UserLogin.UserToken = @UserToken 
                 AND UserLogin.UserTokenExpiration < GETDATE())
        RETURN -203;    -- Token expired

    RETURN 0;
END

当我尝试跑步时:

DECLARE @UserCode nvarchar(250) = N'7C6898E2-0529-4C3F-B4B2-FA69087CDF4A';
DECLARE @UserToken nvarchar(250)= N'DE3B193D-65BC-4F75-970A-932C9F825D81';

SELECT dbo.IsAuthorized(@UserCode,@UserToken) as FunctionResult

SELECT *
FROM [User]
INNER JOIN UserLogin ON [User].UserId = UserLogin.UserId
WHERE
    [User].UserCode = @UserCode
    AND UserLogin.UserToken = @UserToken
    AND UserLogin.UserTokenExpiration > GETDATE()

我得到了这个结果:

==&GT;该函数找不到行

-201

==&GT;查询找到一行

4   7C6898E2-0529-4C3F-B4B2-FA69087CDF4A    Ahmed   ALOUI   TROY    aloui.ahmed@wanadoo.fr  0       0   1   0   /Ressources/img/aloui.jpg   4   73828562FADE36DD6774C6854F52965C    CC6CA2373C2240743D051352BC3AF3C0    DE3B193D-65BC-4F75-970A-932C9F825D81    2016-11-25 16:02:12.083

任何线索?

2 个答案:

答案 0 :(得分:0)

不同之处在于,在您的函数中,您正在运行SELECT并比较该选择的结果以查看它是否大于零(这将不起作用),而在您的原始{{1}中没有使用该函数,如果找到则只返回整个记录。

您可能希望在您的功能中使用此功能:

SELECT

将计算IF (SELECT COUNT([User].UserId) FROM [User] INNER JOIN UserLogin ON [User].UserId = UserLogin.UserId WHERE [User].UserCode = @UserCode AND UserLogin.UserToken = @UserToken AND UserLogin.UserTokenExpiration > GETDATE()) > 0 RETURN 1; 返回的记录数,如果该数字大于零,将从函数返回值1。

答案 1 :(得分:0)

IF EXISTS (SELECT 1
    FROM
       User u
       INNER JOIN UserLogin l
       ON u.UserId = l.UserId
       AND l.UserToken = @UserTokey
       AND l.UserTokenExpiration = GETDATE()
    WHERE
       u.UserCode = @UserCode
)
BEGIN
    RETURN 1;
END

所以你有User.UserId&gt;的方式0应该工作,但仅当从查询返回单个标量数值时。如果返回多个,则会出错。鉴于您所展示的内容似乎是真实的,但也许您只是展示了一些结果等等。无论如何,在功能的其余部分,您使用完美的技术来改变这一点。只需使用IF EXISTS(SELECT....)

请注意,我的一个小小的烦恼包括在WHERE子句中限制连接表而不是ON条件的条件。将它们置于ON中可能会更加优化,但您的意图更清晰,因此我修改了查询以反映该建议。