2016-11-24 98 views
0

我有一個函數來檢查,如果用戶進行身份驗證,但結果是不正確的:SQL Server函數返回意外的結果

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() 

我得到這樣的結果:

==>函數沒有找到行

-201 

==>查詢找到一個線

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

任何線索?

+0

我試過使用EXISTS ... select count(*)...> 0但問題出在函數上,因爲查詢是正確的,當我運行它時它返回正確的結果 –

回答

0

不同之處在於,在你的函數中,你正在運行一個SELECT並比較這個select的結果來看它是否大於零(這將不起作用),而在你的原始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; 

這將算在你SELECT返回的記錄數,如果數大於零,將會從函數返回值1。

+0

計數將是最合適的,只要User.UserId是數字並且查詢產生一個單行(或一個標量值),比較User.UserId> 0和out count就可以工作。 – Matt

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> 0的方式應該工作,但只有從查詢返回單個標量數值。如果返回多個,則會出錯。考慮到你所表現的看起來似乎是真的,但也許你只是展示了一些結果等等。無論如何,在其餘的功能中,你正在使用完美的技術來改變這一點。只需使用IF EXISTS(SELECT....)

請注意,這是我的寵物狗,它包含條件來限制WHERE子句中的連接表而不是ON條件。將它們置於ON可能會更加優化,但您的意圖更清晰,因此我已修改查詢以反映該建議。