Delete query not working in stored procedure - sql

I have an stored procedure in sql server that in first step inserts some data from one table to another and then delete data that inserted in second table from first table; Maybe it's a complicated description, so let see the code:
ALTER PROCEDURE [dbo].[SP_Insert_NotificationUserBulk]
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [dbo].[NotificationUserBulk]
([NotificationId]
,[UserId]
,[IsNotify]
,[IsShow]
,[NotifyMethod]
,[NotifyDateTime]
,[ShowDateTime]
,[IsDeleted]
,[CreatedDate]
,[ModifiedDate])
(SELECT
UserId,
NotificationId,
IsNotify,
IsShow,
NotifyMethod,
NotifyDateTime,
ShowDateTime,
IsDeleted,
CreatedDate,ModifiedDate
FROM NotificationUsers WHERE IsShow=1 OR IsDeleted=1)
DELETE FROM dbo.NotificationUsers WHERE IsShow=1 OR IsDeleted=1
RETURN
END
Insert statement execute successfully and there is no problem but in Delete statement not working and nothing happens.
So what's the problem and how can I fix it?

If this is a one-time or ad hoc query you could try something like this. If it's oltp then you could add TRY/CATCH and return a success/failure variable.
In an explicit transaction with XACT_ABORT ON the query inserts into 'NotificationUsers' table, outputs (the inserted) NotificationId's into a temp table, and deletes from 'NotificationUsers' based on an INNER JOIN with the temp table.
ALTER PROCEDURE [dbo].[SP_Insert_NotificationUserBulk]
AS
SET NOCOUNT ON;
SET xact_abort on;
begin transaction
declare #NotificationId table(NotificationId int primary key);
INSERT INTO [dbo].[NotificationUserBulk]
([NotificationId]
,[UserId]
,[IsNotify]
,[IsShow]
,[NotifyMethod]
,[NotifyDateTime]
,[ShowDateTime]
,[IsDeleted]
,[CreatedDate]
,[ModifiedDate])
output inserted.NotificationId into #NotificationId
SELECT UserId, NotificationId, IsNotify, IsShow, NotifyMethod,
NotifyDateTime, ShowDateTime, IsDeleted, CreatedDate,
ModifiedDate
FROM NotificationUsers
WHERE IsShow=1
OR IsDeleted=1;
DELETE nu
from dbo.NotificationUsers nu
join #NotificationId n on nu.NotificationId=n.NotificationId;
commit
go

please do not use RETURN after DELETE Query, try to simple Query
DELETE FROM dbo.NotificationUsers WHERE IsShow=1 OR IsDeleted=1

Related

"Must declare the scalar variable" error in my created SQL trigger

I get this error
Must declare the scalar variable "#PlanIdTable"
but I have no idea where the problem is:
CREATE TRIGGER [dbo].[plan_status_trigger]
ON [dbo].[PlanTask]
AFTER INSERT, DELETE, UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE(TaskStatus)
BEGIN
DECLARE #PlanIdTable TABLE (Id nvarchar(20))
INSERT INTO #PlanIdTable
SELECT DISTINCT PlanId
FROM dbo.PlanTask
WHERE TaskId IN (SELECT TaskId FROM INSERTED)
UPDATE dbo.[Plan]
SET PlanStatus = dbo.F_computePlanStatus(PlanId)
WHERE PlanId IN (#PlanIdTable)
END
END
GO
Because #PlanIdTable is a table variable, you also have to treat it that way. In the WHERE of your UPDATE query, you should select the Id instead of just using it directly inside the brackets:
UPDATE dbo.[Plan]
SET PlanStatus = dbo.F_computePlanStatus(PlanId)
WHERE PlanId IN (SELECT Id FROM #PlanIdTable)
There's quite a lot of redundant code in your trigger.
This should do the same thing - refresh only PlanStatus for plans that were updated
Be wary of performance issues here. Your updates to [dbo].[PlanTask] won't finish till this trigger finishes, and dbo.F_computePlanStatus(PlanId) is a performance red flag.
Also your existing logic won't work if for example a PlanId is deleted. I've updated the trigger to allow for this.
CREATE TRIGGER [dbo].[plan_status_trigger]
ON [dbo].[PlanTask]
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE(TaskStatus)
UPDATE dbo.[Plan]
SET PlanStatus = dbo.F_computePlanStatus(PlanId)
WHERE EXISTS (
SELECT * FROM
( SELECT PlanId FROM INSERTED
UNION
SELECT PlanId FROM DELETED
) ST WHERE ST.PlanId = Plan.PlanId
)
END
END

How use inserted\deleted table in stored procedure?

I creating triggers for several tables. The triggers have same logic. I will want to use a common stored procedure.
But I don't know how work with inserted and deleted table.
example:
SET #FiledId = (SELECT FiledId FROM inserted)
begin tran
update table with (serializable) set DateVersion = GETDATE()
where FiledId = #FiledId
if ##rowcount = 0
begin
insert table (FiledId) values (#FiledId)
end
commit tran
You can use a table valued parameter to store the inserted / deleted values from triggers, and pass it across to the proc. e.g., if all you need in your proc is the UNIQUE FileID's:
CREATE TYPE FileIds AS TABLE
(
FileId INT
);
-- Create the proc to use the type as a TVP
CREATE PROC commonProc(#FileIds AS FileIds READONLY)
AS
BEGIN
UPDATE at
SET at.DateVersion = CURRENT_TIMESTAMP
FROM ATable at
JOIN #FileIds fi
ON at.FileID = fi.FileID;
END
And then pass the inserted / deleted ids from the trigger, e.g.:
CREATE TRIGGER MyTrigger ON SomeTable FOR INSERT
AS
BEGIN
DECLARE #FileIds FileIDs;
INSERT INTO #FileIds(FileID)
SELECT DISTINCT FileID FROM INSERTED;
EXEC commonProc #FileIds;
END;
You can
select * into #Inserted from inserted
select * into #Deleted from deleted
and then
use these two temp tables in your stored proc
The tables inserted and deleted are only available inside the trigger. You can only use them in run-time. They will then contain the affected rows.
Also, your code might not work as expected if there is not exactly one row inserted.

Updating a Table after some values are inserted into it in SQL Server 2008

I am trying to write a stored procedure in SQL Server 2008 which updates a table after some values are inserted into the table.
My stored procedure takes the values from a DMV and stores them in a table. In the same procedure after insert query, I have written an update query for the same table.
Insert results are populated fine, but the results of updates are getting lost.
But when I try to do only inserts in the stored procedure and I execute the update query manually everything is fine.
Why it is happening like this?
there should not be a problem in this.
below code working as expected.
create procedure dbo.test
as
begin
create table #temp (
name varchar(100) ,
id int
)
insert #temp
select name ,
id
from master..sysobjects
update #temp
set name='ALL Same'
from #temp
select * from #temp
drop table #temp
end
go
Best approach is to use Trigger, sample of AFTER UPDATE trigger is below:
ALTER TRIGGER [dbo].[tr_MyTriggerName]
ON [dbo].[MyTableName] AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
--if MyColumnName is updated the do..
IF UPDATE (MyColumnName)
BEGIN
UPDATE MyTableName
SET AnotherColumnInMyTable = someValue
FROM MyTableName
INNER JOIN Inserted
ON MyTableName.PrimaryKeyColumn = Inserted.PrimaryKeyColumn
END
END

Can a storeProcecdure insert fire Trigger?

SQL Server 2008
I have trigger defined on
TABLE_A for 'INSTEAD OF INSERT' and TABLE_B for 'INSTEAD OF INSERT'.
Both the triggers perform merge with the inserted table.
TABLE_A insert is done by user/code and is working well, trigger for insert is fired.
I have Stored procedure SP_1 inside TABLE_A TRIGGER.
SP_1 Inserts data from TABLE_A into TABLE_B based on some conditions.
But the problem is when the stored procedure (SP_1) is inserting data, the trigger on TABLE_B is not fired and the data is just inserted as it is.
So can stored procedure inserts fire triggers?
Pseudo-code
ALTER TRIGGER [dbo].[trgtable_AInsert] ON [dbo].[TABLE_A]
Instead of INSERT
AS
BEGIN
SET NOCOUNT ON;
IF exists(SELECT * FROM INSERTED)
BEGIN
MERGE
.......
...........
..............
end
EXEC SP_1 #employee_id
end
ALTER TRIGGER [dbo].[trgtableB_Insert] ON [dbo].[TABLE_B]
Instead of INSERT
AS
BEGIN
SET NOCOUNT ON;
IF exists(SELECT * FROM INSERTED)
BEGIN
MERGE
.......
...........
..............
end
end
ALTER PROCEDURE [dbo].[SP_1] #employeeid int
AS
BEGIN
BEGIN TRANSACTION
insert into TABLE_B
.......
...........
..............
from TABLE_A
where employee_ID is #employeeid
COMMIT TRANSACTION
END
Yes triggers can fired by stored procedure inserts!
But I think the problem is that you should try to use AFTER instead of INSTEAD OF triggers in this case. Becasue I can't see all of your code, but it is possible, that the insert is not done because you overrided it in the Instead Of triggers. With AFTER triggers you should have no problems with firing the second trigger.
This is too big for a comment, and needs formatting, so posting as an "answer".
Yes, triggers will fire in this case. Taking your example and slightly modifying it (note the warnings though):
create table Table_A (ID int not null)
go
create table Table_B (ID int not null)
GO
CREATE PROCEDURE [dbo].[SP_1] #employeeid int
AS
BEGIN
BEGIN TRANSACTION
insert into TABLE_B (ID)
SELECT ID from TABLE_A
where ID = #employeeid
COMMIT TRANSACTION
END
GO
Creating the triggers:
CREATE TRIGGER [dbo].[trgtable_AInsert] ON [dbo].[TABLE_A]
Instead of INSERT
AS
BEGIN
SET NOCOUNT ON;
IF exists(SELECT * FROM INSERTED)
BEGIN
MERGE
into Table_A a
using inserted i on a.id = i.id
when not matched then insert (ID) values (i.id);
end
--Wrong code, just for example
declare #employee_id int
select #employee_id = ID from inserted --BAD CODE, Ignores multiple rows
EXEC SP_1 #employee_id
end
GO
CREATE TRIGGER [dbo].[trgtableB_Insert] ON [dbo].[TABLE_B]
Instead of INSERT
AS
BEGIN
SET NOCOUNT ON;
IF exists(SELECT * FROM INSERTED)
BEGIN
MERGE
into Table_B b
using inserted i on b.id = i.id
when not matched then insert (ID) values (i.id+5);
end
end
GO
And executing a trial insert into Table_A:
insert into Table_A (ID) values (1),(2)
select * from Table_B
On my machine, at the present time, I get a final result of a single row with the value "7". Others may run this sample and get the result "6", because triggers only run once per statement, rather than once per row. But as you can see, both triggers have fired.
As i previously mentioned in the comments #András Ottó
Merge
using(... = "column with possible null values" AND
... = ... AND
... = ...
)
of merge was not working correctly and the records were always inserted.
1 = 1 and E=E and NULL=NULL is not true. (of-course sql 101)
I have overlooked this column and did not place where clause properly to get rid of null values so ended up inserting all the time. Fixing that everything ended up working.
Thanks for the help Every1. Cheers
Apologies.
I'm not going to mark it answered because it is purely my mistake which was not fully mentioned in the question.

After insert, update trigger not running

I have two triggers After Insert or Update and Instead of Insert. It appears that the after trigger is not running or sending the correct data.
I have verified the correct operation of Z_UpdateStageTable stored procedure and the Instead of Insert trigger. Removing the Instead of Insert trigger doesn't have any affect. The After Insert, Update trigger was working correctly at one time, I haven't made any changes to it. I have tried deleting it and adding it, but it still doesn't run or have the correct data.
Any Ideas?
Instead of Insert:
ALTER TRIGGER [DeleteExistingFilter]
ON [dbo].[Z_MobileSyncFilters]
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM Z_MobileSyncFilters WHERE UserID = (SELECT UserID FROM INSERTED);
INSERT INTO Z_MobileSyncFilters
SELECT *
FROM INSERTED;
END
After Insert, Update:
TRIGGER [UpdateStageTable]
ON [dbo].[Z_MobileSyncFilters]
AFTER INSERT,UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #AllWos AS VARCHAR(5000);
DECLARE #PmWos AS VARCHAR(5000);
DECLARE #RepWos AS VARCHAR(5000);
SET #AllWos = (SELECT AllWos FROM INSERTED);
SET #RepWos = (SELECT AllWos FROM INSERTED);
SET #PmWos = (SELECT AllWos FROM INSERTED);
EXEC Z_UpdateStageTable #AllWos;
EXEC Z_UpdateStageTable #RepWos;
EXEC Z_UpdateStageTable #PmWos;
END
Is there a typo in the SET part of the AFTER trigger? You're selecting the same thing into three different variables.
Rather than confirming the behavior of Z_UpdateStageTable, I'd try to replace it with something dirt simple (a parameterless sql statement, say) to test whether the trigger's being called. It's possible that the sproc's not being called with what you think it's being called with.
You can add PRINT statements to the trigger and manually insert from ManagementStudio/Enterprise Manager to see where the trigger fails.
I see a problem when you insert multiple records in a single statement, as the SELECT FROM Inserted will return more than 1 record.
You can also update the SET statement to SELECT #Var = AllWos FROM Inserted
Hold on a second, if userid is your PK then Z_MobileSyncFilters will not have data yet, this is also an instead of trigger
this wholw block doesn't do anything really, why do you need this trigger?
DELETE FROM Z_MobileSyncFilters WHERE UserID = (SELECT UserID FROM INSERTED);
INSERT INTO Z_MobileSyncFilters
SELECT *
FROM INSERTED;
you second trigger is flawed because it will faile if you have a multi row operation
why do you have 2 insert trigger (1 instead 1 after) on this table?