Хранимая процедура входа в систему - SQL Server - PullRequest
0 голосов
/ 01 октября 2019

У меня есть хранимая процедура для входа в систему. Есть три параметра: i) электронная почта ii) пароль iii) IsActive. Я хочу проверить различные аспекты и вернуть битовое значение для каждого случая. Я попытался:

CREATE PROCEDURE [dbo].[SP_Login] 
    @Email VARCHAR(100),
    @Password VARCHAR(50),
    @ReturnValue INT
AS
BEGIN

    -- No User
    IF NOT EXISTS (Select * From AdminAccount Where Email=@Email and Password = @Password)
        BEGIN
            SET @ReturnValue = 0
        END

    -- Active User
    ELSE IF EXISTS (Select * From AdminAccount Where Email=@Email and Password = @Password and IsActive='1')
        BEGIN
            SET @ReturnValue = 1
        END

    -- Not Active user
    ELSE IF EXISTS (Select * From AdminAccount Where Email=@Email and Password = @Password and IsActive='0')
        BEGIN
            SET @ReturnValue = 2
        END

    -- Email Not Exist
    ELSE IF NOT EXISTS (Select * From AdminAccount Where Email=@Email)
        BEGIN
            SET @ReturnValue = 3
        END

    -- Password Not Match
    ELSE IF EXISTS (Select * From AdminAccount Where Email=@Email)
        BEGIN
            SET @ReturnValue = 4
        END
END

Теперь проблема в том, что он использует различные запросы SELECT. Есть ли способ минимизировать или оптимизировать код, не теряя смысла.

Ответы [ 3 ]

0 голосов
/ 01 октября 2019

Попробуйте это

declare @AdminAccount table (Email  varchar(100), Pass  varchar(50), IsActive bit)

insert into @AdminAccount 
values ('mail1@m.com', 'abc', 1), ('mail2@m.com', '123', 0)

--Testing values
declare @Email VARCHAR(100) = 'mail2@m.com',
        @Password VARCHAR(50) = '123',
        @ReturnValue tinyint

--Temporary table: It avoid us to query the table many times
declare @userData table (Email  varchar(100), Pass  VARCHAR(50), IsActive bit)

    if exists ( select top 1 1 from @AdminAccount where Email = @Email ) 
        insert into @userData
        select Email, Pass, IsActive
        from @AdminAccount 
        where Email = @Email
    else
     begin
        if not exists ( select top 1 1 from @AdminAccount where Email = @Email and Pass = @Password ) 
            set @ReturnValue = 0
        else 
            set @ReturnValue = 3    --it will never return this value (3)
    end

    select  @ReturnValue = 
                        case 
                            when @Email = Email and @Password = Pass and IsActive = 1 then 1
                            when @Email = Email and @Password = Pass and IsActive = 0 then 2
                          else 4
                        end 
    from @userData 

    select @ReturnValue as RV   
0 голосов
/ 01 октября 2019

Попробуйте это:

IF EXISTS (SELECT * FROM AdminAccount WHERE Email=@Email)
 BEGIN
    SELECT  @ReturnValue = 
            CASE WHEN Password = @Password AND IsActive='1' THEN 1  -- Password match, Active User
                WHEN Password = @Password AND IsActive='0' THEN 2   -- Password match, Inactive User
                WHEN Password <> @Password AND IsActive='1' THEN 3  -- Active User, Password does not match
                WHEN Password <> @Password AND IsActive='0' THEN 4  -- Inactive User, Password does not match
                ELSE 0                                              -- Details (Email and Password) do not match 
            END
    FROM AdminAccount WHERE Email=@Email
END
ELSE IF NOT EXISTS (SELECT * FROM AdminAccount WHERE Email=@Email)
 BEGIN
    SET @ReturnValue = 0
END
0 голосов
/ 01 октября 2019

Поскольку вопрос не в том, как хранить пароли в базе данных, я не буду затрагивать этот вопрос в этом ответе.

Первое, на что я должен указать, это то, что ваша процедура никогда не вернет значение3. Если параметр Email не соответствует учетной записи, ваше условие возврата 0 всегда будет выполняться до того, как будет выполнено условие возврата 3. По этой причине я исключил его в этом ответе.

Если ваша цель состоит в том, чтобы избежать нескольких запросов внутри вашей хранимой процедуры (хорошая идея), вы можете выполнить ту же логику, используя один запрос и локальные переменные. Вот подтверждение концепции с использованием Microsoft SQL Server 2014.

CREATE TABLE AdminAccount (
Email VARCHAR(100),
Password VARCHAR(50),
IsActive BIT
)

INSERT INTO AdminAccount (Email,Password,IsActive) VALUES    ('test@test.com','password',1)
INSERT INTO AdminAccount (Email,Password,IsActive) VALUES ('test2@test.com','password2',0)
INSERT INTO AdminAccount (Email,Password,IsActive) VALUES ('test3@test.com','password3',0)

SELECT * FROM AdminAccount

DECLARE @EmailParam VARCHAR(100) = 'test2@test.com'
DECLARE @PasswordParam VARCHAR(50) = 'password'
DECLARE @ReturnValue INT


DECLARE @LocalEmail VARCHAR(100)
DECLARE @LocalPassword VARCHAR(50)
DECLARE @LocalActive BIT

SELECT @LocalEmail = Email, @LocalPassword = Password, @LocalActive = IsActive FROM AdminAccount WHERE Email=@EmailParam

SET @ReturnValue = 
CASE 
    WHEN @LocalEmail IS NULL AND @LocalPassword IS NULL 
    THEN 0 -- No User
    WHEN @LocalPassword = @PasswordParam AND @LocalActive = 1 
    THEN 1 -- Active User
    WHEN @LocalPassword = @PasswordParam AND @LocalActive = 0
    THEN 2 -- Inactive User
    WHEN @LocalPassword <> @PasswordParam
    THEN 4 -- Invalid Password
END

SELECT @ReturnValue

Вот обновленная хранимая процедура с использованием приведенной выше логики локальной переменной.

CREATE PROCEDURE [dbo].[SP_Login] 
    @Email VARCHAR(100),
    @Password VARCHAR(50),
    @ReturnValue INT OUTPUT
AS
BEGIN
    -- Declare local variables to avoid multiple queries
    DECLARE @LocalEmail VARCHAR(100)
    DECLARE @LocalPassword VARCHAR(50)
    DECLARE @LocalActive BIT

    -- Gather data
    SELECT @LocalEmail = Email, @LocalPassword = Password, @LocalActive = IsActive FROM AdminAccount WHERE Email=@EmailParam

    SET @ReturnValue = 
    CASE 
        WHEN @LocalEmail IS NULL AND @LocalPassword IS NULL 
        THEN 0 -- No User
        WHEN @LocalPassword = @PasswordParam AND @LocalActive = 1 
        THEN 1 -- Active User
        WHEN @LocalPassword = @PasswordParam AND @LocalActive = 0
        THEN 2 -- Inactive User
        WHEN @LocalPassword <> @PasswordParam
        THEN 4 -- Invalid Password
    END

END
...