Yet another primary key exception - sql

Last year I ask this question: What could be causing the primary key exception?
But I still have another error in this stored procedure: randomly I get
INSERT EXCEPTION WITH FOREIGN KEY "FK_Sessions" WITH TABLE
"Sessions", column "id".
CREATE PROCEDURE [dbo].[MyProcedure]
#sessionId varchar(512),
#variable varchar(350),
#value image
AS
BEGIN
BEGIN TRAN
DECLARE #result int = 0;
DECLARE #locked bit;
IF (SELECT COUNT(*) FROM Sessions WITH(ROWLOCK,HOLDLOCK) WHERE id = #sessionId) = 0
BEGIN
SET #result = -1;
END
ELSE BEGIN
DELETE Variables WITH(ROWLOCK,HOLDLOCK) WHERE sessionId = #sessionId AND variable = #variable
IF #value IS NOT NULL
BEGIN
INSERT Variables VALUES(#sessionId, #variable, #value, 0)
END
END
COMMIT TRAN
RETURN #result
END
Any ideas? Thanks again

Related

SQL Server stored procedure: verify CRUD operation success/failure using output variable

I am trying to create a SQL Server stored procedure to handle updates to a table using some dynamic SQL. The table name required for the update is stored in a table that correlates a table id to a category id. Once the table name is retrieved and the table id is not null, I update the table using a dynamic SQL query as shown below:
CREATE PROCEDURE [dbo].[SP_EBS_CustomForms_SetCategoryData]
(#flag int output,
#cat_id int,
#sort int,
#value varchar(50),
#active int,
#enum int)
AS
BEGIN
DECLARE #tbl as varchar(50)
DECLARE #tbl_id as int
DECLARE #sql nvarchar(max)
BEGIN TRY
SET #tbl_id = (SELECT [tbl_id]
FROM [demodata].[dbo].[ebscustomforms_cattable]
WHERE cat_id = #cat_id)
IF #tbl_id IS NOT NULL
BEGIN
SET #tbl = (SELECT table_name
FROM ebscustomforms_enumtable
WHERE tbl_id = #tbl_id)
SET #sql = 'UPDATE ' + #tbl + ' SET [sort_order] = #sort, [value] = #value, [active] = #active WHERE [enum_id] = #enum'
EXECUTE sp_executesql #sql, N'#sort int, #value varchar(50), #active int, #enum int', #sort, #value, #active, #enum
SET #flag = 0
RETURN #flag
END
END TRY
BEGIN CATCH
IF ##ERROR <> 0
BEGIN
SET #flag = 1;
RETURN #flag
END
END CATCH
END
I want this stored procedure to return an int value indicating whether the stored procedure was successful (0) or failed (1) updating the table.
Points of error are as follows:
#tbl_id variable is null
#tbl is either null or an empty varchar
The table to be updated does not have a record where [enum_id] = #enum
I have noticed that when I try to update a record that does not exist, the procedure seems to return as successful i.e. #flag = 0. However, I would imagine that an error should be thrown because the record does not exist.

Creating an Instead of insert Trigger SQL

I am a DBA with my company. I am trying to create trigger that will check any insert statement for duplicates first then if none allow the original insert. Not even sure this can be done. The insert statements may be written by various users so the statements will never be the same. All I have found so far is the check for duplicates but the insert statement is then hard coded in the trigger. My plan is also to check update as well, but it is not important right now.
Here is my current code.
ALTER TRIGGER [dbo].[BlockDuplicatesOnTable]
ON [dbo].[blockduplicates]
Instead of INSERT, Update
AS
BEGIN
SET NOCOUNT ON;
Declare #ProviderAcctNumber nvarchar(50)
Declare #Referredby int
Declare #Action as char(1)
Declare #Count as int
Set #Action = 'I'
Select #Count = Count(*) from DELETED
IF #Count > 0
Begin
Set #Action = 'D'
Select #Count = count(*) from INSERTED
IF #Count > 0
Set #Action = 'U'
IF #Action = 'I'
Begin
IF not exists (Select 1 from inserted as i
inner join dbo.blockduplicates as b
on i.ProviderAcctNumber = b.ProviderAcctNumber
and i.Referredby = b.Referredby)
Begin
--execute original insert
End
Else
Begin
Print 'Duplicate insert'
Raiserror ('Duplicate Entry for Insert',16,1);
Return
End
End
Else IF #Action = 'U'
Begin
Select #ProviderAcctNumber = ProviderAcctNumber, #Referredby = Referredby from inserted
IF Not exists (Select 1 from deleted where ProviderAcctNumber = #ProviderAcctNumber and Referredby = #Referredby)
Begin
Print 'Update Statement is True';
End
Else
Begin
Print 'duplicate'
Raiserror ('Duplicate Entry for Update',16,1);
Return
End
End
End
End;

RAISERROR Dosn't Work Inside CATCH With ROLLBACK TRANSACTION

I created a Stored Procedure to Insert Into 2 Table With Transaction to make sure That Both Inserts Done and I Used TRY and CATCH to Handle The Errors .. The Problem Is In The Catch Statement I Put ROLLBACK TRANS and RAISERROR The RoLLBACK Works But The Procedure Dose not RAISERROR
Here is The Code
ALTER PROC SP_InsertPlot
#PlotName nvarchar(50),
#GrossArea int,
#SectorName Nvarchar(50),
#PlotYear int,
#OwnerName Nvarchar(50),
#Remarks text,
#NumberOfPlants INT,
#NetArea INT,
#Category Nvarchar(50),
#Type Nvarchar(50),
#Variety Nvarchar(50),
#RootStock Nvarchar(50),
#PlantDistance Decimal(18,2)
AS
BEGIN
DECLARE #PlotID INT
SET #PlotID = (SELECT ISNULL(MAX(PlotID),0) FROM Plots) + 1
DECLARE #SectorID INT
SET #SectorID = (SELECT SectorID FROM Sectors WHERE SectorName = #SectorName)
DECLARE #OwnerID INT
SET #OwnerID = ( SELECT OwnerID FROM Owners WHERE OwnerName = #OwnerName)
DECLARE #CategoryID INT
SET #CategoryID = (SELECT CategoryID FROM Categories WHERE CategoryName = #Category)
DECLARE #TypeID INT
SET #TypeID = (SELECT TypeID FROM Types WHERE TypeName = #Type)
DECLARE #VarietyID INT
SET #VarietyID = (SELECT VarietyID FROM Varieties WHERE VarietyName = #Variety)
DECLARE #RootStockID INT
SET #RootStockID = (SELECT RootStockID FROM RootStocks WHERE RootStockName = #RootStock)
DECLARE #PlotDescID INT
SET #PlotDescID = (SELECT ISNULL(MAX(PlotDescID),0) FROM PlotDescriptionByYear) + 1
BEGIN TRY
SET XACT_ABORT ON
SET NOCOUNT ON
IF(SELECT Count(*) FROM Plots WHERE PlotName = #PlotName) = 0
BEGIN
BEGIN TRANSACTION
INSERT INTO Plots (PlotID,PlotName,GrossArea,SectorID,PlantYear,OnwerID,Remarks)
VALUES(#PlotID,#PlotName,#GrossArea,#SectorID,#PlotYear,#OwnerID,#Remarks)
INSERT INTO PlotDescriptionByYear (PlotDescID, PlantYear, NumberOfPlants,PlotID,NetArea,CategoryID,TypeID,VarietyID,RootStockID,PlantDistance)
VALUES(#PlotDescID,YEAR(GETDATE()),#NumberOfPlants,#PlotID -1,#NetArea,#CategoryID,#TypeID,#VarietyID,#RootStockID,#PlantDistance)
COMMIT TRANSACTION
END
END TRY
BEGIN CATCH
IF(XACT_STATE())= -1
BEGIN
ROLLBACK TRANSACTION
RAISERROR('This Plot Is Already Exists !!',11,1)
END
END CATCH
END
By the way i tried to change the Severity and I tried ##TRANCOUNT instead of XACT_STATE and the Same Problem Happens Which is When I Exec Proc and Pass an Existing Data To The Parameters The Transaction Roll back and did not rise the error
Change IF(XACT_STATE())= -1 to IF(XACT_STATE()) <> 0 and your problem will be done.

SQL Server stored procedure compile error

Stored procedure is:
CREATE PROCEDURE CountUtily
#domain varchar(50),
#count int,
#totalCount int OUT
AS
BEGIN
SET NOCOUNT ON
SET #totalCount=0
IF (EXISTS (SELECT #totalCount = count
FROM FormFillerAuto2_DomainCount
WHERE domain = #domain))
BEGIN
SET #totalCount = #totalCount + #count
UPDATE FormFillerAuto2_DomainCount
SET count = #totalCount
WHERE domain = #domain
END
ELSE
BEGIN
INSERT INTO FormFillerAuto2_DomainCount (domain, count)
VALUES (#domain, #count)
END
END
Error:
Incorrect syntax near '='. Incorrect syntax near the keyword 'ELSE'.
your Select #totalCount = count does not return a bool. Try setting #totalCount before the if evaluates and eval the count in the if
CREATE PROCEDURE CountUtily
#domain varchar(50),
#count int,
#totalCount int OUT
AS BEGIN
SET NOCOUNT ON
SET #totalCount=0
SELECT #totalCount=count FROM FormFillerAuto2_DomainCount WHERE
IF (#totalCount > 0)
begin
SET #totalCount=#totalCount+#count
UPDATE FormFillerAuto2_DomainCount SET count=#totalCount WHERE domain=#domain
end
ELSE
begin
INSERT INTO FormFillerAuto2_DomainCount (domain, count) VALUES (#domain, #count)
end
end
See EXISTS
Specifies a subquery to test for the existence of rows. it Returns
TRUE if a subquery contains any rows,it accept restricted SELECT statement, The INTO keyword is not allowed.
the problem here is you can't set the value inside the Exists.
Try
alter PROCEDURE CountUtily
#domain varchar(50),
#count int,
#totalCount int OUT
AS BEGIN
SET NOCOUNT ON
SET #totalCount=0;
IF (EXISTS (SELECT [count] FROM FormFillerAuto2_DomainCount WHERE domain=#domain))
begin
SELECT #totalCount=[count] FROM FormFillerAuto2_DomainCount WHERE domain=#domain
UPDATE FormFillerAuto2_DomainCount SET count=#totalCount WHERE domain=#domain
end
ELSE
begin
INSERT INTO FormFillerAuto2_DomainCount (domain, count) VALUES (#domain, #count)
end
end
I believe you are missing ; to mark the end of the statement here. Again, count is a reserve word and so escape it using []. Your posted procedure can be modified to
CREATE PROCEDURE CountUtily(
#domain varchar(50),
#count int,
#totalCount int OUT)
AS BEGIN
SET NOCOUNT ON;
SET #totalCount=0;
SELECT #totalCount=[count] FROM FormFillerAuto2_DomainCount WHERE domain=#domain;
IF (#totalCount IS NOT NULL)
begin
SET #totalCount=#totalCount+#count;
UPDATE FormFillerAuto2_DomainCount SET [count]=#totalCount WHERE domain=#domain;
end
ELSE
INSERT INTO FormFillerAuto2_DomainCount (domain, [count]) VALUES (#domain, #count);
end
You've made this query too complicated with the count and totalcount variables; all of which you do not need.
So, you want to update the "count" field of your "FormFillerAuto2_DomainCount" when the field "domain" matches a parameter #domain; or you want to Insert it if it doesn't exist.
OK, let's do that using ##RowCount.
UPDATE FormFillerAuto2_DomainCount SET [count] = ([count]+#count) where [domain] = #domain
If (##ROWCOUNT > 0)
BEGIN
return 1 --updated : or return whatever you need to show it updated
END
ELSE
BEGIN
INSERT INTO FormFillerAuto2_DomainCount ([domain], [count]) VALUES (#domain, #count)
return 2 --inserted : or return whatever you need to show it inserted
END
It seems like your update is a bit screw up.. It should be
UPDATE TABLENAME
SET COLUMNNAME = VALUE
WHERE CONDITION
Readability will help understand and maintain code.

getting the last inserted id from previous insert statement

I am having a stored procedure with two insert statement, where I want to insert the ID of the first insert statement into the second one.
CREATE PROC [dbo].[Log_Action]
#action_description VARCHAR(MAX),
#creator_id INT,
#entity VARCHAR(50),
#entity_identifier UNIQUEIDENTIFIER
AS
BEGIN
DECLARE #return_value BIT;
BEGIN TRY
INSERT INTO Action_Lookup (action_description)
VALUES (#action_description);
INSERT INTO Audit ([user_id], action_id, CREATED, [guid], entity, entity_identifier)
VALUES (#creator_id, SCOPE_IDENTITY(), GETDATE(), NEWID(), #entity, #entity_identifier);
SET #return_value = 1;
RETURN #return_value;
END TRY
BEGIN CATCH
SET #return_value = 0;
RETURN #return_value;
END CATCH
END
the problem that SCOPE_IDENTITY() returns null, I also tried ##IDENTITY and IDENT_CURRENT but non works.
Try output clause:
CREATE PROC [dbo].[Log_Action]
#action_description VARCHAR(MAX),
#creator_id INT,
#entity varchar(50),
#entity_identifier uniqueidentifier
AS
BEGIN
DECLARE #return_value bit;
BEGIN TRY
INSERT INTO Action_Lookup (action_description)
OUTPUT
#creator_id,
inserted.[id], -- in [] there should be actual name of identity column
GETDATE(),
NEWID(),
#entity,
#entity_identifier
INTO Audit ([user_id], action_id, created, [guid], entity, entity_identifier)
VALUES (#action_description);
set #return_value = 1;
return #return_value;
END TRY
BEGIN CATCH
set #return_value = 0;
return #return_value;
END CATCH
END