MSSQL Trigger for update is working only once - sql

I'm going to create a trigger for update. Purpose of this trigger is that If muadurum column is changed , take the old value of mua_tarih in table fkayitlar and insert to another table mua_tarihleri.
My code block like;
ALTER TRIGGER [dbo].[trgr_fkayit_update]
ON [dbo].[fkayitlar]
AFTER UPDATE
AS
DECLARE #mua_durum_once NVARCHAR(10)
DECLARE #mua_durum_sonra NVARCHAR(10)
DECLARE #mua_tarih_once DATE
DECLARE #mua_yapan_once NVARCHAR(25)
DECLARE #kisi_id INT
Take the old value;
SELECT
#kisi_id=kayitid,
#mua_durum_once=muayenedurum,
#mua_tarih_once=muayenetarih,
#mua_yapan_once=mua_yapan
FROM deleted
Take the new value;
SELECT #mua_durum_sonra=muayenedurum FROM inserted
Check if value is changed ; if changed, Insert #mua_tarih to table mua_tarihleri with #kisi_id and #mua_yapan_once
IF #mua_durum_once='OLDU'
AND #mua_durum_sonra='OLMADI'
AND #mua_tarih_once IS NOT NULL
BEGIN
INSERT INTO mua_tarihleri(kayitid,mua_tarihi,mua_yapan)
VALUES(#kisi_id,#mua_tarih_once,#mua_yapan_once)
END
My problem is When I update more than one row in table fkayitlar,Trigger is working, but I see only one inserted row in table mua_tarihleri (only working once). I need to see more than one.(should be working more than once) Are not Triggers working on more than one process? or How can I solve this my problem?

The trigger only occurs once when the table is updated, no matter how many rows are updated. Therefore, you have to write your trigger body to operate on a set of rows, not a single row as you have done.
Should be something like:
ALTER TRIGGER [dbo].[trgr_fkayit_update]
ON [dbo].[fkayitlar]
AFTER UPDATE
AS
INSERT INTO mua_tarihleri(kayitid,mua_tarihi,mua_yapan)
SELECT deleted.kayitid, deleted.muayenedurum, deleted.muayenetarih, deleted.mua_yapan
FROM deleted
JOIN inserted ON deleted.kayitid = inserted.kayitid
WHERE deleted.muayenedurum='OLDU'
AND inserted.muayenedurum='OLMADI'
AND muayenetarih IS NOT NULL

Related

Creating a trigger instead of UPDATE on a view

I have a view and a trigger that overwrites UPDATE. I try to understand the code, however I am having some troubles with line from deleted and from inserted - Are these automatically created by original update? Does it mean that if I call this trigger, first the update gets called and then the trigger?
create trigger updateView on View
instead of UPDATE as
begin
declare #nameK VARCHAR(100), #addresK VARCHAR(100), #nameZ VARCHAR(100), #number INT, #date DATE;
declare #nameKo VARCHAR(100), #addresKo VARCHAR(100), #nameZo VARCHAR(100), #numbero INT, #dateo DATE; -- 'o'ld
declare insCur cursor for select name, addres, bandName, number, date from inserted;
declare delCur cursor for select name, addres, bandName, number, date from deleted;
open insCur;
open delCur;
...
This trigger will fire instead of performing the update. The inserted and deleted tables are made available so that you can determine:
The new values for each updated row in inserted
The previous (in this case current, since the normal update operation has not been performed) values from each updated row in deleted
The convention of inserted and deleted is used regardless of the type of trigger. So, for example, in an after update trigger, which simply follows the execution of a normal update, the deleted table would be the primary way to know the previous values.
The deleted contains old values, the inserted - new values.
There are options: AFTER UPDATE or BEFORE UPDATE which you can set to see behavior which you want.
About Deleted and Inserted:
UPDATE dbo.Client SET Name = 'John' WHERE Name = 'Steve'
you will have: deleted value 'Steve', inserted value 'John'
Also I would recommend to avoid using cursors inside triggers, i.e. it can hit performance a lot.

SQL Insert, Update Trigger - Can you update the inserted table?

I have an SQL Trigger FOR INSERT, UPDATE I created which basically does the following:
Gets a LineID (PrimaryID for the table) and RegionID From the Inserted table and stores this in INT variables.
It then does a check on joining tables to find what the RegionID should be and if the RegionID is not equal what it should be from the Inserted table, then it should update that record.
CREATE TRIGGER [dbo].[TestTrigger]
ON [dbo].[PurchaseOrderLine]
FOR INSERT, UPDATE
AS
-- Find RegionID and PurchaseOrderLineID
DECLARE #RegionID AS INT
DECLARE #PurchaseOrderLineID AS INT
SELECT #RegionID = RegionID, #PurchaseOrderLineID = PurchaseOrderLineID FROM Inserted
-- Find PurchaserRegionID (if any) for the Inserted Line
DECLARE #PurchaserRegionID AS INT
SELECT #PurchaserRegionID = PurchaserRegionID
FROM
(...
) UpdateRegionTable
WHERE UpdateRegionTable.PurchaseOrderLineID = #PurchaseOrderLineID
-- Check to see if the PurchaserRegionID has a value
IF #PurchaserRegionID IS NOT NULL
BEGIN
-- If PurchaserRegionID has a value, compare it with the current RegionID of the Inserted PurchaseOrderLine, and if not equal then update it
IF #PurchaserRegionID <> #RegionID
BEGIN
UPDATE PurchaseOrderLine
SET RegionID = #PurchaserRegionID
WHERE PurchaseOrderLineID = #PurchaseOrderLineID
END
END
The problem I have is that it is not updating the record and I'm guessing, it is because the record hasn't been inserted yet into the PurchaseOrderLine table and I'm doing an update on that. But can you update the row which will be inserted from the Inserted table?
The major problem with your trigger is that it's written in assumption that you always get only one row in INSERTED virtual table.
SQL Server triggers are statement-triggers not row-triggers. You have to take that fact into consideration.
Now if I understand correctly the logic behind this trigger then you need just one update statement in it
CREATE TRIGGER TestTrigger ON PurchaseOrderLine
FOR INSERT, UPDATE
AS
UPDATE l
SET RegionID = u.PurchaserRegionID
FROM PurchaseOrderLine l JOIN INSERTED i
ON l.PurchaseOrderLineID = i.PurchaseOrderLineID JOIN
(
SELECT PurchaseOrderLineID, PurchaserRegionID
FROM UpdateRegionTable -- !!! change this for your proper subquery
) u ON l.PurchaseOrderLineID = u.PurchaseOrderLineID
For this example I've created a fake table UpdateRegionTable. You have to change it to the proper query that returns PurchaseOrderLineID, PurchaserRegionID (in your code you replaced it with ...). Make sure that it returns all necessary rows, not one.
Here is SQLFiddle demo
I think the problem could be that you are making the update to PurchaceOrderLine inside the trigger that is monitoring updates to the same table as well. Try to alter the trigger to just monitor the inserts, than if this works, you can make some changes or break your trigger on two: one for inserts, another for updates.
This has been resolved. I resolved the problem by adding the trigger to another table as the IF #PurchaserRegionID IS NOT NULL was always false.

SQL Trigger to update row

I need a SQL trigger that would zero pad a cell whenever its inserted or updated. Was curious if its best practice to append two strings together like I'm doing in the update command. Is this be best way to do it?
CREATE TRIGGER PadColumnTenCharsInserted ON Table
AFTER INSERT
AS
DECLARE
#pad_characters VARCHAR(10),
#target_column NVARCHAR(255)
SET #pad_characters = '0000000000'
SET #target_column = 'IndexField1'
IF UPDATE(IndexField1)
BEGIN
UPDATE Table
SET IndexField1 = RIGHT(#pad_characters + IndexField1, 10)
END
GO
Your padding code looks fine.
Instead of updating every row in the table like this:
UPDATE Table
update just the row that triggered the trigger:
UPDATE updated
Also, you've still got some extraneous code -- everything involving #target_column. And it looks like you're not sure if this is an INSERT trigger or an UPDATE trigger. I see AFTER INSERT and IF UPDATE.
Two questions:
What are you doing with #target_column? You declare it and set it with a column name, but then you never use it. If you intend to use the variable in your subsequent SQL statements, you may need to wrap the statements in an EXECUTE() or use sp_executesql().
The syntax "UPDATE Table..." is OK for your update statement assuming that "Table" is the name of the table you are updating. What seems to be missing is a filter of some kind. Or did you really intend for that column to be updated for every row in the whole table?
One way to handle this would be to declare another variable and set it with the PK of the row that is updated, then use a where clause to limit the update to just that row. Something like this:
DECLARE #id int
SELECT #id = Record_ID FROM INSERTED
-- body of your trigger here
WHERE Record_ID = #id
I like your padding code. It looks good to me.

INSERT trigger to update a field that is NOT NULL in the same table

I have a situation where I need to merge two product tables into one and need to keep both id fields. The Id field is the pk and an identity column. On insert I want to update the prodId to match the Id of the newly inserted row. This is what I have but I get an error saying that I cannot insert null into ProductId. What am I doing wrong?
ALTER TRIGGER SyncId
ON Product
FOR INSERT
AS
BEGIN
DECLARE #ID INT
SET #ID = (SELECT ID FROM Inserted)
UPDATE Product SET
ProdId = #ID
WHERE
Id = #ID
END
You could create an INSTEAD OF trigger for the INSERT. You would then have to recreate the actual INSERT logic. You might need a view of the table for the trigger to sit on though... I don't recall if an INSERT within the trigger will work or not and can't test it right now.
Also, your trigger as written will only work if a single row is being updated. You should always write your triggers to be able to handle multiple rows in the INSERTED and DELETED tables.

SQL Server 2005 triggers

I created a trigger on a table for updates. If any update happens, I want to store the old value in separate table. I am trying to get the old value from "inserted" table, but this table is not populated with old values after update.
Here is the sample code:
CREATE TRIGGER [dbo].[Logs_Update]
ON [dbo].[Logs] AFTER UPDATE
AS
DECLARE #url varchar(50)
BEGIN
SELECT #url = i.url
FROM INSERTED i
INSERT INTO dbo.Triggers_tbl
(ID, URL)
VALUES
(1000, #url)
END
I get #url as null from the inserted table.
Please let me know what is wrong with the trigger
The DELETED table contains the "old" values and the "INSERTED" table contains the "new" values.
To add to this, the INSERTED and DELETED tables may contain multiple rows if your update affects multiple rows and therefore you should probably run your insert with an INSERT SELECT rather than a variable.
INSERT INTO dbo.Triggers_tbl(URL) SELECT d.url FROM DELETED d
The "old" values (after an UPDATE) are available in the Deleted pseudo-table:
CREATE TRIGGER [dbo].[Logs_Update]
ON [dbo].[Logs]
AFTER UPDATE
AS
DECLARE #url varchar(50)
SELECT #url = d.url from deleted d
INSERT INTO dbo.Triggers_tbl(ID,URL) VALUES(1000,#url)
As HLGEM correctly commented on, the OP's code is assuming the trigger will be called for each row separately - which is not correct.
In that light, the trigger code really ought to deal with a set of rows being updated, and thus it should be something like:
CREATE TRIGGER [dbo].[Logs_Update]
ON [dbo].[Logs]
AFTER UPDATE
AS
INSERT INTO dbo.Triggers_tbl(ID,URL)
SELECT 1000, d.url
FROM Deleted d
or something like that.
The records that were updated are in the DELETED virtual table, not INSERTED. Change "from inserted" to "from deleted" and that should work.