Stored procedure for Login Application - sql

I have a table with the user details like
id
fname
lname
role
branch
email
password
I have a stored procedure for the login validation which takes the values of email and password, validates and send out the success message.
The validation is working now. I need to fetch the values of fname, lname, role and branch too.
Here is the code:
USE [Project]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER Procedure [dbo].[usp_loginuser]
(#Email varchar(100),
#password varchar(100)
)
AS
BEGIN
DECLARE #msg nvarchar(2048)
SET NOCOUNT ON
--select * from dbo.userdetails where email=#userEmail and pwd=#password
BEGIN TRY
Declare #flag bit
SET #flag = 0
IF EXISTS(Select * from userdetails
where ltrim(rtrim(email)) = ltrim(rtrim(#Email)) AND ltrim(rtrim(pwd)) = ltrim(rtrim(#password))
AND isactive = 1)
BEGIN
SET #flag =1;
END
ELSE
BEGIN
SET #flag =0;
END
SELECT #flag [IsSuccess]
END TRY
BEGIN CATCH
SET #msg = error_message()
RAISERROR (#msg, 16, 1)
END CATCH
SET NOCOUNT OFF
END

Here is the code
ALTER Procedure [dbo].[usp_loginuser]
(#Email varchar(100),
#password varchar(100),
#fname varchar(100) output,
#lname varchar(100) output
)
AS
BEGIN
DECLARE #msg nvarchar(2048)
SET NOCOUNT ON
BEGIN TRY
Declare #flag bit
SET #flag = 0
IF EXISTS(Select #fname = fname, #lname = lname from userdetails
where ltrim(rtrim(email)) = ltrim(rtrim(#Email)) AND ltrim(rtrim(pwd)) = ltrim(rtrim(#password))
AND isactive = 1)
BEGIN
SET #flag =1;
END
ELSE
BEGIN
SET #flag =0;
END
SELECT #flag [IsSuccess], #fname, #lname
END TRY
BEGIN CATCH
SET #msg = error_message()
RAISERROR (#msg, 16, 1)
END CATCH
SET NOCOUNT OFF
END

BEGIN TRY
Declare #flag bit
SET #flag = 0
IF EXISTS(Select * from userdetails
where ltrim(rtrim(email)) = ltrim(rtrim(#Email)) AND ltrim(rtrim(pwd)) = ltrim(rtrim(#password))
AND isactive = 1)
BEGIN
SET #flag =1;
END
ELSE
BEGIN
SET #flag =0;
END
SELECT fname, lname, role, branch from userdetails
where ltrim(rtrim(email)) = ltrim(rtrim(#Email)) AND ltrim(rtrim(pwd)) = ltrim(rtrim(#password))
END TRY
If you get an empty data set, its a failure else success

Related

How to return the output of stored procedure into a string variable in SQL Server

I want to execute a stored procedure in SQL Server and assign the output to a string.
CREATE PROCEDURE sp_Check_User_Password
#name NVARCHAR(30),
#email NVARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #pass NVARCHAR(50)
IF EXISTS(SELECT dbo.Mitarbeiter.Name, dbo.Mitarbeiter.Email
FROM dbo.Mitarbeiter
WHERE dbo.Mitarbeiter.Name = #name
AND dbo.Mitarbeiter.Email = #email
BEGIN
SET #pass = dbo.Mitarbeiter.Password
END
ELSE
BEGIN
SET #pass = null
END
RETURN #pass
END
I have changed what I wrote wrong
Have a look on below sample, just add your stuff and it will work
CREATE PROCEDURE return_string
(#param1 NVARCHAR(10),
#param2 NVARCHAR(10),
#output NVARCHAR(10) OUT)
AS
BEGIN
IF (1=1)
SET #output = 'here'
else
SET #output = null
END
to test
declare #out nvarchar(10)
exec return_string 'firdt param', 'second param', #out out
select #out
I hope this will help you achive what you need.
So your SP would look like:
CREATE PROCEDURE sp_Check_User_Password
(
#name nvarchar(30),
#email nvarchar(50),
#pass nvarchar(50) OUT
)
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS(SELECT 1
FROM dbo.Mitarbeiter
WHERE dbo.Mitarbeiter.Name = #name
and dbo.Mitarbeiter.Email = #email)
BEGIN
SET #pass = (SELECT dbo.Mitarbeiter.Name
FROM dbo.Mitarbeiter
WHERE dbo.Mitarbeiter.Name = #name
and dbo.Mitarbeiter.Email = #email)
END
ELSE
BEGIN
SET #pass = null
END
END
I'll take a stab at it. Is this what you're trying to do?
CREATE PROCEDURE sp_Check_User_Password
#name nvarchar(30),
#email nvarchar(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #pass nvarchar(50) = null
IF EXISTS(SELECT dbo.Mitarbeiter.Email FROM dbo.Mitarbeiter
WHERE dbo.Mitarbeiter.Name = #name and dbo.Mitarbeiter.Email = #email)
BEGIN
SELECT #pass = dbo.Mitarbeiter.Email FROM dbo.Mitarbeiter
WHERE dbo.Mitarbeiter.Name = #name and dbo.Mitarbeiter.Email = #email
END
PRINT #pass
END

Problems with ROLLBACK TRANSACTION inside try/catch

I'm having this error when I try to execute this code:
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 0, current count = 1.
I know the problem is on the sp [dbo].[QueueInsert], the sp has an error and it goes directly to the catch. It's funny because the first one (EXEC [dbo].[BacthInsert]) is inserting a summary record and after running the sp, I see the record, so is doing a commit and not doing a rollback. What's wrong with this code? thanks!
CREATE PROCEDURE [cnfg].[SendEmail]
(
,#Employees [dbo].[Employees] readonly
,#ApplicationName NVARCHAR(256)
,#ErrorMsg NVARCHAR(300) = NULL OUTPUT
)
AS
BEGIN
DECLARE #ReturnVal INT
DECLARE #ApplicationId UNIQUEIDENTIFIER
DECLARE #NewIdBatch INT
DECLARE #ID INT
DECLARE #EmployeeId INT
DECLARE #Index INT = 1
DECLARE #Total INT
SET NOCOUNT ON;
SET XACT_ABORT ON;
SET #ReturnVal = 0;
SET #ErrorMsg = '';
SET #ApplicationId = [GetId](#ApplicationName);
IF (#ApplicationId IS NULL)
BEGIN
SET #ReturnVal = 1;
SET #ErrorMsg = 'The Application Name does not exist in the database';
Goto ProcedureExit
END
----------------------------------------------------------
BEGIN TRY -- Start Main TRY
----------------------------------------------------------
BEGIN TRANSACTION;
EXEC [dbo].[BacthInsert]
#ParameterId = 1
,#ID = #NewSendEmailBatchId OUTPUT
,#ErrorMsg = #ErrorMsg OUTPUT
IF ( #ErrorMsg <> '' )
BEGIN
SET #ReturnVal = 1;
SET #ErrorMsg = 'There was an error trying to insert data into [dbo].[BacthInsert] table';
RAISERROR(#ErrorMsg, 16, 1)
END
SELECT ROW_NUMBER() OVER ( ORDER BY EmployeeId ) Row,
EmployeeId
INTO #EmpIds
FROM #Employees
SELECT #Total = COUNT(*) FROM #EmpIds
WHILE ( #Index <= #Total )
BEGIN
SELECT #EmployeeId=EmployeeId FROM #EmpIds WHERE Row = #Index
EXEC [dbo].[QueueInsert]
#SendEmailBatchId = #NewIdBatch
,#ID = #ID OUTPUT
,#ErrorMsg = #ErrorMsg OUTPUT
IF ( #ErrorMsg <> '' )
BEGIN
SET #ReturnVal = 1;
SET #ErrorMsg = 'There was an error trying to insert data into [dbo].[QueueInsert] table';
RAISERROR(#ErrorMsg, 16, 1)
END
SET #Index+=1;
END
COMMIT TRANSACTION;
----------------------------------------------------------
END TRY -- End Main TRY
----------------------------------------------------------
----------------------------------------------------------
BEGIN CATCH -- Start Main CATCH
----------------------------------------------------------
SELECT ERROR_MESSAGE()
IF (XACT_STATE()) = -1
BEGIN
ROLLBACK TRANSACTION;
END;
----------------------------------------------------------
END CATCH -- End Main CATCH
----------------------------------------------------------
ProcedureExit:
RETURN #ReturnVal;
END

Must declare the scalar variable error for stored procedure

I have following stored procedure:
CREATE procedure validateLogin
(
#password varchar(200),
#username varchar(100),
#IpAddress varchar(100)
)
AS
BEGIN
Declare #qry varchar(max), #LockedIp varchar(max), #LockedTime DateTime, #TimeDifference int;
set #qry = 'select IdUser, UserName, FirstName, LastName, idOrg, Users.idRole, Roles.Title as [Role], Allowed_IP from Users, Roles where Users.idRole = Roles.idRole
and lower(UserName) = #username and [password] = #password' ;
select
#LockedIp = isnull(Allowed_IP,''),
#LockedTime = isnull(LockedTime, getDate())
from Users
where UserName = ISNULL(#username,'');
SELECT
#TimeDifference = DATEDIFF(MINUTE, #LockedTime, GETDATE())
IF exists(select * from Users where UserName = #username AND Password = #password AND Active = 1)
BEGIN
IF exists(select * from Users where UserName = #username AND isnull(IsLocked, 0) = 1)
BEGIN -- BE1
IF(#LockedIp = #IpAddress)
BEGIN --BE2
IF (#TimeDifference >5)
BEGIN --BE5
UPDATE Users
SET IsLocked = 0, LockedTime = null
WHERE UserName = ISNULL(#username,'')
exec(#qry);
END --BE5
ELSE
BEGIN
select 'Your Account has been Locked.Try after some time' as Error
END
END --BE2
Else IF(#LockedIp!=#IpAddress)
BEGIN --BE4
UPDATE Users
SET IsLocked = 0, LockedTime = null
WHERE UserName = isnull(#username,'')
exec(#qry);
END --BE4
END -- BE1
Else
BEGIN --BE3
exec(#qry);
END -- BE3
END
END
Go
When I execute this through:
exec validateLogin '|161|217|4|51','admin','127.0.0.1'
I get following error:
Msg 137, Level 15, State 2, Line 3
Must declare the scalar variable "#username".
I have declared this variable in my parameter list, then also error is showing up.
Please help me.
How can I resolve this?
EXEC() will execute in a different scope, so your parameters are not found. You should use sp_executesql and add your parameters that way:
DECLARE #qry NVARCHAR(MAX);
SET #qry = N'select IdUser,UserName,FirstName,LastName,idOrg,Users.idRole,Roles.Title as [Role],Allowed_IP
from Users,Roles
where Users.idRole=Roles.idRole
and lower(UserName)=#username
and [password]=#password' ;
EXECUTE sp_executesql #qry,
N'#username varchar(100), #password varchar(200)',
#Username,
#Password;

Getting Request Timeout sometimes from only one SP?

I have a lot of stored procedures. But I am only getting Request Timeout sometimes only for this SP ?
ALTER PROCEDURE [dbo].[Insertorupdatedevicecatalog]
(#OS NVARCHAR(50)
,#UniqueID VARCHAR(500)
,#Longitude FLOAT
,#Latitude FLOAT
,#Culture VARCHAR(10)
,#Other NVARCHAR(200)
,#IPAddress VARCHAR(50)
,#NativeDeviceID VARCHAR(50))
AS
BEGIN
SET NOCOUNT ON;
DECLARE #TranCount INT;
SET #TranCount = ##TRANCOUNT;
DECLARE #OldUniqueID VARCHAR(500) = ''-1'';
SELECT #OldUniqueID = [UniqueID] FROM DeviceCatalog WHERE (#NativeDeviceID != '''' AND [NativeDeviceID] = #NativeDeviceID);
BEGIN TRY
IF #TranCount = 0
BEGIN TRANSACTION
ELSE
SAVE TRANSACTION Insertorupdatedevicecatalog;
DECLARE #Geo GEOGRAPHY = geography::STGeomFromText(''POINT('' + CONVERT(VARCHAR(100), #Longitude) + '' '' + CONVERT(VARCHAR(100), #Latitude) + '')'', 4326);
IF EXISTS(SELECT 1 FROM DeviceCatalog WHERE [UniqueID] = #UniqueID)
BEGIN
DECLARE #OldGeo GEOGRAPHY
,#OldCity NVARCHAR(100)
,#OldCountry NVARCHAR(100)
,#OldAddress NVARCHAR(100);
SELECT #OldGeo = [LastUpdatedLocationFromJob]
,#OldCity = [City]
,#OldCountry = [Country]
,#OldAddress = [Address]
FROM DeviceCatalog
WHERE [UniqueID] = #UniqueID;
UPDATE DeviceCatalog
SET [OS] = #OS
,[Location] = #Geo
,[Culture] = #Culture
,[Other] = #Other
,[IPAddress] = #IPAddress
WHERE [UniqueID] = #UniqueID;
IF (#OldGeo IS NULL OR #OldAddress IS NULL OR #OldCity IS NULL OR #OldCountry IS NULL OR ISNULL(#Geo.STDistance(#OldGeo) / 1000,0) > 50)
BEGIN
UPDATE DeviceCatalog
SET [Lastmodifieddate] = Getdate()
WHERE [UniqueID] = #UniqueID;
END
END
ELSE
BEGIN
INSERT INTO DeviceCatalog
([OS]
,[UniqueID]
,[Location]
,[Culture]
,[Other]
,[IPAddress]
,[NativeDeviceID])
VALUES (#OS
,#UniqueID
,#Geo
,#Culture
,#Other
,#IPAddress
,#NativeDeviceID);
IF(#OldUniqueID != ''-1'' AND #OldUniqueID != #UniqueID)
BEGIN
EXEC DeleteOldAndroidDeviceID #OldUniqueID, #UniqueID;
END
END
LBEXIT:
IF #TranCount = 0
COMMIT;
END TRY
BEGIN CATCH
DECLARE #Error INT, #Message VARCHAR(4000), #XState INT;
SELECT #Error = ERROR_NUMBER() ,#Message = ERROR_MESSAGE() ,#XState = XACT_STATE();
IF #XState = -1
ROLLBACK;
IF #XState = 1 AND #TranCount = 0
rollback
IF #XState = 1 AND #TranCount > 0
ROLLBACK TRANSACTION Insertorupdatedevicecatalog;
RAISERROR (''Insertorupdatedevicecatalog: %d: %s'', 16, 1, #error, #message) ;
END CATCH
END
The timeout occurs due to two updates to same table inside same transaction. You could avoid it with a case statement. Also whole IF ELSE can be replaced with a merge.
MERGE INTO DeviceCatalog DC
USING (SELECT #UniqueID AS UniqueID) T ON (DC.UniqueID = T.UniqueID)
WHEN MATCHED THEN
UPDATE SET [OS] = #OS
,[Location] = #Geo
,[Culture] = #Culture
,[Other] = #Other
,[IPAddress] = #IPAddress
,[Lastmodifieddate] = (CASE
WHEN (LastUpdatedLocationFromJob IS NULL OR [Address] IS NULL OR [City] IS NULL OR [Country] IS NULL OR ISNULL(#Geo.STDistance(LastUpdatedLocationFromJob) / 1000,0) > 50)
THEN Getdate()
ELSE [Lastmodifieddate]
END)
WHEN NOT MATCHED THEN
INSERT INTO DeviceCatalog
([OS]
,[UniqueID]
,[Location]
,[Culture]
,[Other]
,[IPAddress]
,[NativeDeviceID])
VALUES (#OS
,#UniqueID
,#Geo
,#Culture
,#Other
,#IPAddress
,#NativeDeviceID)
WHEN NOT MATCHED BY SOURCE AND #OldUniqueID != ''-1'' AND #OldUniqueID != #UniqueID THEN
DELETE;
Try it and check whether this is what you expected.
Already discussed here
You can achieve it using sp_getapplock in TSQL.
But you need a wrapper storedproc or batch for this. Check the following example it will help you to desing your wrapper sp/batch statement.
Sample Code Snippet
Create table MyTable
(
RowId int identity(1,1),
HitStartedAt datetime,
HitTimestamp datetime,
UserName varchar(100)
)
Go
Create proc LegacyProc (#user varchar(100), #CalledTime datetime)
as
Begin
Insert Into MyTable
Values(#CalledTime, getdate(), #user);
--To wait for 10 sec : not required for your procedures, producing the latency to check the concurrent users action
WAITFOR DELAY '000:00:10'
End
Go
Create Proc MyProc
(
#user varchar(100)
)
as
Begin
Declare #PorcName as NVarchar(1000), #CalledTime datetime
Begin Tran
--To get the Current SP Name, it should be unique for each SP / each batch
SET #PorcName = object_name(##ProcID)
SET #CalledTime = Getdate()
--Lock the Current Proc
Exec sp_getapplock #Resource = #PorcName, #LockMode = 'Exclusive'
--Execute Your Legacy Procedures
Exec LegacyProc #user, #CalledTime
--Release the lock
Exec sp_releaseapplock #Resource = #PorcName
Commit Tran
End
You are doing two seperate updates on the DeviceCatalog table where [UniqueID] = #UniqueID in the same transaction.
I bet your locking/request timeout issue is happening when:
IF (#OldGeo IS NULL OR #OldAddress IS NULL OR #OldCity IS NULL OR #OldCountry IS NULL OR ISNULL(#Geo.STDistance(#OldGeo) / 1000,0) > 50) is true.
Try something like this in place of the two updates.
Obviously test in dev first.
In the else clause, you want to have it insert something if the when is false. Here I am just inserting the current before update field contents.
UPDATE DeviceCatalog
SET [OS] = #OS
,[Location] = #Geo
,[Culture] = #Culture
,[Other] = #Other
,[IPAddress] = #IPAddress
,[Lastmodifieddate] =
case when (
#OldGeo is NULL
OR
#OldAddress is NULL
OR
#OldCity is NULL
OR
#OldCountry is NULL
OR
ISNULL(#Geo.STDistance(#OldGeo) / 1000,0) > 50
) then Getdate()
else [Lastmodifieddate]
end
WHERE [UniqueID] = #UniqueID

Dont want Select variable displaying values

It might be simple but I been having trouble figuring out.
I have a piece of code(Similar to Below Code) where I am assigning bunch of values to bunch of variables via select, it does the job but when I am running it I am getting result set which is causing my SSMS to crash is there way to avoid this....
DECLARE #Name VARCHAR(100)
DECLARE #LastName VARCHAR(100)
DECLARE #Address VARCHAR(100)
SELECT TOP 1
#Name = Name
#LastName = LastName
#Address = Address
From Person.Address
Where Name = 'Name'
Order By ID
I am using the above code in a loop where I am processing around 3-400K rows and pass this variables to a stored procedure, each top 1 select statement throws a result set causing my SSMS to crash I dont really need the select top 1 values to be displayed, any idea how to get rid of this?....
Any help would be much appreciated.
---As requested below is the code, I have hashed few things but this is what it is and I am running it from Query Analayzer as this is only 1 time process so we dont need SP to be created.
DECLARE #retstat INT
DECLARE #Name VARCHAR(255)
DECLARE #Lang TINYINT
DECLARE #Address CHAR(10)
DECLARE #ID INT
DECLARE #BranchSeqNo INT
DECLARE #AddressCode VARCHAR(10)
DECLARE #Address1 VARCHAR(50)
DECLARE #City VARCHAR(30)
DECLARE #State VARCHAR(3)
DECLARE #PostalCode VARCHAR(15)
DECLARE #Country VARCHAR(30)
SET #ID = NULL
UPDATE RAWClaimTable Set Processed = 0 where Processed is null
UPDATE RAWClaimTable SET ErrorCode = NULL ,ErrorMessage = NULL ,Processed = 0
WHERE ErrorMessage IS NOT NULL AND CLAIMID is null
WHILE EXISTS ( SELECT *
FROM RAWClaimTable
WHERE Processed = 0 )
BEGIN
-----Initialize Default Variables
SET #Lang = 0
SET #Address = 'Import'
SET #SaveMode = 0
SET #ID = Null
SELECT TOP 1
#LossDate = LossDate ,
#ClaimDate = ClaimDate ,
#OpenDate = OpenDate ,
#Receivedate = ReceiVeDate ,
#Name = Name ,
#Address = Address ,
#Address1 = Address1 ,
#City = City ,
#State = State ,
#PostalCode = PostalCode ,
#Country = Country
FROM RAWClaimTable
WHERE Processed = 0
ORDER BY ClaimID
BEGIN TRY
EXEC #RetStat = Usp_ProcessRawData #Lang, #Address, #SaveMode, #ID OUT,
#BranchSeqNo, #OriginalBranchSeqNo, #IncidentID,
#AssignmentTypeCode, #PartnershipID, #AccountID,
END TRY
BEGIN CATCH
SELECT #RetStat = ##Error
if ##Trancount > 0 rollback tran
IF #RetStat != 0
BEGIN
update RAWClaimTable set Errormessage = ERROR_MESSAGE() where ClaiMKey = #Name
END
END CATCH
IF #ID IS NOT NULL
BEGIN
UPDATE RAWClaimTable
SET ClaimID = #ID ,
Processed = 1
WHERE ClaiMKey = #Name
END
ELSE
BEGIN
UPDATE RAWClaimTable
SET Processed = 1
WHERE ClaiMKey = #Name
END
END
Use a CURSOR to loop thru your rows!
SET #Lang = 0
SET #Address = 'Import'
SET #SaveMode = 0
SET #ID = Null
DECLARE my_cursor CURSOR FOR
SELECT LossDate, ClaimDate, OpenDate, ReceiVeDate, Name, Address,
Address1, City, State, PostalCode, Country
FROM RAWClaimTable
WHERE Processed = 0
OPEN my_cursor
FETCH NEXT FROM my_cursor
INTO #LossDate, #ClaimDate, #OpenDate, #Receivedate, #Name, #Address,
#Address1, #City, #State, #PostalCode, #Country
WHILE ##FETCH_STATUS = 0
BEGIN
BEGIN TRY
EXEC #RetStat = Usp_ProcessRawData #Lang, #Address, #SaveMode, #ID OUT,
#BranchSeqNo, #OriginalBranchSeqNo, #IncidentID,
#AssignmentTypeCode, #PartnershipID, #AccountID,
END TRY
BEGIN CATCH
SELECT #RetStat = ##Error
if ##Trancount > 0 rollback tran
IF #RetStat != 0
BEGIN
update RAWClaimTable set Errormessage = ERROR_MESSAGE()
where ClaiMKey = #Name
END
END CATCH
IF #ID IS NOT NULL
BEGIN
UPDATE RAWClaimTable
SET ClaimID = #ID ,
Processed = 1
WHERE ClaiMKey = #Name
END
ELSE
BEGIN
UPDATE RAWClaimTable
SET Processed = 1
WHERE ClaiMKey = #Name
END
FETCH NEXT FROM my_cursor
INTO #LossDate, #ClaimDate, #OpenDate, #Receivedate, #Name, #Address,
#Address1, #City, #State, #PostalCode, #Country
END