stored procedure exists details not validate - sql

Im create the stored procedure , I want to check UserCategoryCode and UserCategoryName, existing record, im make a existing record , but not a correctly working it for the UserCategoryCode, how can i do it? im try to do it, but not work, (Its work for the UserCategoryName )
SP
ALTER PROCEDURE [dbo].[UserCategories_InsertUpdate]
#UserCategoryId int,
#UserCategoryCode varchar(50),
#UserCategoryName varchar(250),
#Remarks nvarchar(max),
#StatusId int,
-- #StatusChangeDate DATETIME,
#CreateId int,
#Mode varchar(50),
#iOutput int output
AS
BEGIN
BEGIN TRY
BEGIN TRAN
IF #Mode = 'Add'
BEGIN
IF NOT EXISTS (SELECT UserCategoryCode,UserCategoryName FROM UserCategories WHERE UserCategoryCode = #UserCategoryCode AND UserCategoryName = #UserCategoryName)
BEGIN
INSERT INTO UserCategories(
UserCategoryCode,
UserCategoryName,
StatusId,
StatusChangeDate,
CreateBy,
CreatedDate,
Remarks
)
VALUES(
#UserCategoryCode,
#UserCategoryName,
#StatusId,GETDATE(),
#CreateId,GETDATE(),
#Remarks
)
SET #iOutput = 1 --save successful--
END
ELSE
BEGIN
SET #iOutput=-3 --existing record--
END
END
ELSE IF #Mode = 'Modify'
BEGIN
UPDATE UserCategories
SET UserCategoryCode = #UserCategoryCode,
UserCategoryName = #UserCategoryName,
StatusId = #StatusId,
Remarks = #Remarks,
EditBy = #CreateId,
EditDate = GETDATE()
WHERE UserCategoryId = #UserCategoryId
SET #iOutput = 2 --save successful--
END
COMMIT
END TRY
BEGIN CATCH
print ERROR_MESSAGE()
SET #iOutput = -2 --sp error--
ROLLBACK
END CATCH
END

oh finally its working , i found the solution ,
IF NOT EXISTS (SELECT UserCategoryCode FROM UserCategories WHERE UserCategoryCode = #UserCategoryCode)
IF NOT EXISTS (SELECT UserCategoryName FROM UserCategories WHERE UserCategoryName = #UserCategoryName)
BEGIN
INSERT INTO UserCategories(
UserCategoryCode,
UserCategoryName,
StatusId,
StatusChangeDate,
CreateBy,
CreatedDate,
Remarks
)
VALUES(
#UserCategoryCode,
#UserCategoryName,
#StatusId,GETDATE(),
#CreateId,GETDATE(),
#Remarks
)
SET #iOutput = 1 --save successful--
END
ELSE
BEGIN
SET #iOutput=-3 --existing record--
END
ELSE
BEGIN
SET #iOutput=-5 --existing record--
END
END
ELSE IF #Mode = 'Modify'
BEGIN
UPDATE UserCategories
SET UserCategoryCode = #UserCategoryCode,
UserCategoryName = #UserCategoryName,
StatusId = #StatusId,
Remarks = #Remarks,
EditBy = #CreateId,
EditDate = GETDATE()
WHERE UserCategoryId = #UserCategoryId
SET #iOutput = 2 --save successful--
END
COMMIT
END TRY
BEGIN CATCH
print ERROR_MESSAGE()
SET #iOutput = -2 --sp error--
ROLLBACK
END CATCH
END
and code behind
else if (output == -3)
{
lblMsg.Text = "Already Exists!";
lblMsg.ForeColor = System.Drawing.Color.Orange;
}
else if (output == -5)
{
lblMsg.Text = "Already Exists!";
lblMsg.ForeColor = System.Drawing.Color.Orange;
}

Related

Stored procedure for Login Application

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

Making SQL statement efficient and easy to understand

I have problem that I have to make my code shorter .
code:
IF #result_var = #expected_value
BEGIN
INSERT INTO reports.consistencycheckhistory VALUES
(
Getdate(),
#rule_guid,
'Ok',
#result_var
)
IF CONVERT(DATE,#check_time) <> CONVERT(DATE, Sysdatetime())
BEGIN
UPDATE reports.consistencycheckrules
SET ok_days_count =#ok_days_count + 1 ,
last_check_time=#check_time
where rule_guid=#rule_guid
END
END
ELSE
BEGIN
INSERT INTO reports.consistencycheckhistory VALUES
(
Getdate(),
#rule_guid,
'Error',
#result_var
)
UPDATE reports.consistencycheckrules
SET ok_days_count=0,
last_check_time=#check_time
WHERE rule_guid=#rule_guid
END
There have to be only 1 insert and 1 update that is what my boss is saying but I don't know if it is possible.
IF #result_var = #expected_value
BEGIN
SET #Status = 'Ok'
END
ELSE
BEGIN
SET #Status = 'Error'
END
IF CONVERT(DATE,#check_time) <> CONVERT(DATE, Sysdatetime())
BEGIN
SET #ok_days_count = #ok_days_count + 1;
END
ELSE
BEGIN
SET #ok_days_count = 0;
END
INSERT INTO reports.consistencycheckhistory VALUES
(
Getdate(),
#rule_guid,
#Status,
#result_var
)
UPDATE reports.consistencycheckrules
SET ok_days_count = #ok_days_count ,
last_check_time=#check_time
where rule_guid=#rule_guid
You could use case statements within insert and within update. Not that it would make it much easier to understand, but would fulfill your boss' wish.
Try this (might need a bit of tweaking):
INSERT INTO reports.consistencycheckhistory
VALUES
(
Getdate(),
#rule_guid,
CASE
WHEN #result_var = #expected_value
then 'Ok'
ELSE 'Error"
END,
#result_var
)
UPDATE reports.consistencycheckrules
SET
ok_days_count =#ok_days_count +
CASE
WHEN CONVERT(DATE,#check_time) <> CONVERT(DATE,Sysdatetime())
then 1
ELSE
0
END,
last_check_time=#check_time
where rule_guid=#rule_guid
In the query there is case where you do not have to update columns, i.e. #result_var = #expected_value and CONVERT(DATE,#check_time) = CONVERT(DATE, Sysdatetime())
DECLARE #Should_Update bit
SET #Should_Update=0
IF #result_var = #expected_value
BEGIN
SET #Status = 'Ok'
END
ELSE
BEGIN
SET #Status = 'Error'
END
IF(#result_var = #expected_value)
BEGIN
IF CONVERT(DATE,#check_time) <> CONVERT(DATE, Sysdatetime())
BEGIN
SET #Should_Update=1
SET #ok_days_count = #ok_days_count + 1;
END
END
ELSE
BEGIN
SET #Should_Update=1
SET #ok_days_count = 0;
END
INSERT INTO reports.consistencycheckhistory VALUES
(
Getdate(),
#rule_guid,
#Status,
#result_var
)
UPDATE reports.consistencycheckrules
SET ok_days_count = #ok_days_count ,
last_check_time=#check_time
where rule_guid=#rule_guid AND #Should_Update=1
IF #result_var = #expected_value
BEGIN
SET #Status = 'Ok'
END
ELSE
BEGIN
SET #Status = 'Error'
END
IF #Status = 'Ok'
BEGIN
IF CONVERT(DATE, #check_time) <> CONVERT(DATE, Sysdatetime())
BEGIN
SET #ok_days_count = #ok_days_count + 1;
END
ELSE
BEGIN
#ok_days_count=#ok_days_count
END
end
ELSE
BEGIN
SET #ok_days_count = 0;
end
INSERT INTO reports.consistencycheckhistory VALUES
(
Getdate(),
#rule_guid,
#Status,
#result_var
)
UPDATE reports.consistencycheckrules
SET ok_days_count = #ok_days_count,
last_check_time = #check_time
WHERE rule_guid = #rule_guid
This seems like the right answer

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

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

assisatnce in the sql function

I have posted below written code earlier and got the correct code with the removal of errors, but my criteria is not satisfying, below is the raw data im passing as the paramater
2007:10113:/I/69071/MLI/Eldridge
and in return the output should be "69071", for this i have given the below function but im not gettig the output,a nd i have kept some other condition to satisfy other requirements also, please help me.
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON --2007:10113:/I/69071/MLI/Eldridge
go
ALTER FUNCTION [dbo].[Empnum] (#RAWDATA NVARCHAR(300))
RETURNS VARCHAR(30)
AS
BEGIN
DECLARE #TEMP1 NVARCHAR(300), #EMPNUM NVARCHAR(10), #TEMP2 NVARCHAR(300), #TEMP3 NVARCHAR(300)
SET #TEMP3 = 'Disabled'
SET #EMPNUM=''
SET #TEMP2 = #RAWDATA
IF( CHARINDEX(#TEMP3,#RAWDATA,1) = 0)
BEGIN
-- SET #EMPNUM='11'
IF ISNUMERIC(SUBSTRING(#RAWDATA,1,1)) = 1
BEGIN
--
IF((LEN(#RAWDATA) - LEN(REPLACE(#TEMP2,'/','')))>1)
BEGIN
SET #RAWDATA=SUBSTRING(#RAWDATA,CHARINDEX('/',#RAWDATA)+1,LEN(#RAWDATA))
SET #RAWDATA=SUBSTRING(#RAWDATA,CHARINDEX('/',#RAWDATA)+1,LEN(#RAWDATA))
SET #RAWDATA=SUBSTRING(#RAWDATA,1,CHARINDEX('/',#RAWDATA)-1)
IF( CHARINDEX('*C',#RAWDATA) = 0 OR
CHARINDEX('CV',#RAWDATA) = 0 OR
CHARINDEX('AV',#RAWDATA) = 0 OR
CHARINDEX('LV',#RAWDATA) = 0 )
BEGIN
SET #EMPNUM = ''
RETURN #EMPNUM
END
ELSE
BEGIN
IF ISNUMERIC(SUBSTRING(#RAWDATA,1,1)) = 1
BEGIN
SET #EMPNUM = #RAWDATA
RETURN #EMPNUM
END
ELSE
IF((SUBSTRING(#RAWDATA,1,1)='C') AND ISNUMERIC(SUBSTRING(#RAWDATA,2,1)) = 1)
BEGIN
SET #EMPNUM = SUBSTRING(#RAWDATA,2,LEN(#RAWDATA))
RETURN #EMPNUM
END
END
END
END
END
RETURN #EMPNUM
END
I have found the error in my code, and changed the "="o "<>"
IF( CHARINDEX('*C',#RAWDATA) <> 0 OR
CHARINDEX('CV',#RAWDATA) <> 0 OR
CHARINDEX('AV',#RAWDATA) <> 0 OR
CHARINDEX('LV',#RAWDATA) <> 0 )
BEGIN
SET #EMPNUM = ''
RETURN #EMPNUM
END