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

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

Related

Delete query not working in stored procedure

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

Update trigger for update new table from another

I have 2 tables mpayment and account. When someone updates data in mpayment, then the trigger should automatically update the account table with the newly updated data. I wrote this trigger on my mpayment table, but when I try to update some data, I get an error:
The row value update or deleted either do make the row unique or they alter multiplerows [2 rows]
This is my trigger that I am trying to use
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[mpacupdate]
ON [dbo].[mpayment]
AFTER UPDATE
AS
BEGIN
DECLARE #pid AS NCHAR(10)
DECLARE #memid AS NCHAR(10)
DECLARE #pdate AS DATE
DECLARE #pamount AS MONEY
DECLARE #flag AS INT
SELECT #pid = list.pid FROM inserted list;
SELECT #memid = list.memid FROM inserted list;
SELECT #pdate = list.pdate FROM inserted list;
SELECT #pamount = list.pamount FROM inserted list;
SELECT #flag = list.flag FROM inserted list;
BEGIN
UPDATE [dbo].[account]
SET memid = #memid, pdate = #pdate,
pamount = #pamount, flag = #flag
WHERE pid = #pid
END
END
Your trigger is assuming that only 1 row will be updating at a time; it shouldn't. Treat the data as what it is, a dataset (not a set a scalar values).
This maynot fix the problem, as there's no sample data here to test against. I'm also not really sure that what you're after here is the right design choice, however, there's no information on what that is. Generally, you shouldn't be repeating data across tables; if you need data from another table then use a JOIN, don't INSERT or UPDATE both. If they become out of sync you'll start to get some really odd results I imagine.
Anyway, on track, this is probably what you're looking for, however, please consider the comments I've made above:
ALTER TRIGGER [dbo].[mpacupdate] ON [dbo].[mpayment]
AFTER UPDATE
AS BEGIN
UPDATE A
SET memid = i.memid,
pdate = i.pdate,
pamount = i.pamount,
flag = i.flag
FROM dbo.Account A
JOIN inserted i ON A.pid = i.pid;
END

SQL Server transaction fails and table gets locked

My stored procedure is like this
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Bid_Create]
#BidType int,
#ClientId int,
#BidDate date,
#EmailNotificationStatus int,
#BidStatus int,
#BidAmount int,
#ProductId int
AS
DECLARE #highestBid int;
BEGIN
BEGIN TRY
BEGIN TRANSACTION
SET NOCOUNT ON;
SET #highestBid = (SELECT Max(wf_bid.BidAmount) AS HighestBitAmount
FROM wf_bid
WHERE wf_bid.ProductId = #ProductId)
IF #highestBid is NULL OR #highestBid < #BidAmount
BEGIN
UPDATE wf_bid
SET BidStatus = '1'
WHERE Id = (SELECT TOP 1 id
FROM [wf_bid]
WHERE BidAmount = (SELECT MAX(BidAmount)
FROM [wf_bid]
WHERE ProductId = #ProductId
AND ClientId = #ClientId))
INSERT INTO wf_bid (BidType, ClientId, BidDate, EmailNotificationStatus, BidStatus)
VALUES (#BidType, #ClientId, #BidDate, #EmailNotificationStatus, #BidStatus)
END
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
END CATCH
END
Everything looks okay to me. But once I run this, table is getting locked. No other query on the table works (I think it is because transaction is not getting committed).
Can anyone point out what is wrong with this query? And how can I unlock the table?
But once I run this, table is getting locked
This may be due to update taking many locks,which in turn may be due to predicate not being sargable. Though this update locks(U) lock will be released as soon as the predicate is not matched.You will experience blocking
One more reason ,why this update may block your whole table is when this transaction acquires more than 5000 locks..
another reason can be when your transaction fails after committing so many rows and it has to do a lot of rollback work
Above are the reasons ,i could think of,where you can experience table is locked feeling
to troubleshoot that,you will need to check lockings blokcings using below query
select resource_type,resource_Database_id,
request_mode,request_type,request_Status,request_session_id
from sys.dm_tran_locks
where request_session_id=<<your update session id>>
also you are accessing table many times,for getting max.you can rewrite it like below
;with cte
as
(
select top (1) with ties id,bidstatus from
wf_bid
where ProductId=#ProductId and ClientId=#ClientId)
order by
row_number() over (partition by id order by bid_Amount desc)
)
update cte
set bidstatus=1

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?