Insert trigger will not work properly - sql

I am trying to create a database trigger that will update certain characters in a field for a table when a user inserts data into the table...
Ex.
ID EXCHANGE LEADRT
1 new L-3
2 new 3
3 new 5
So I would want to leave id 1 alone because the format for the LEADRT is correct but ids 2 and 3 are not.
CREATE TRIGGER triggerupdate ON PoleUnits FOR INSERT,
UPDATE AS
if not exists (select * from Poleunits where LEADRT like '%L-%')
update PoleUnits set LEADRT = STUFF (LEADRT, 1, 0,'L-');
Any ideas why I can't get this to work or better suggestions on how to accomplish this?

In insert and update triggers you have access to a specific table called inserted where the rows to be inserted/updated are held. Those are not real tables, they are just logical tables with the same structure as the table on which the trigger fired.
Your current logic works on the original table, thus working with all the existing data, but not with the data you are actually inserting, i.e. it will update everything except the data you actually want updated. Something like this could work:
CREATE TRIGGER triggerupdate ON PoleUnits
FOR INSERT, UPDATE AS
update PoleUnits
set LEADRT = STUFF (PoleUnits.LEADRT, 1, 0,'L-')
from PoleUnits
inner join inserted -- this is basically a self join
on PoleUnits.ID = inserted.ID
where PoleUnits.LEADRT not like '%L-%'
This will only update those rows in PoleUnits that are being inserted, and only if their LEADRT field is not in the L- format.

Related

Interbase SQL trigger

Interbase, Sql, trigger. Can't really understand how to write a trigger of this kind: I have several tables. Each one has a document type, status and an unique number. One table in which i wish to create a trigger is a table that holds a file i post, a status of posting, a doctype corresponding to a table and a unique number linking to a record in the corresponding table. I want to change document status in the corresponding table based on the unique number to a certain status depending on the post result (status) that i change after posting. How can I do it?
Trigger T1 will be executed after update on TABLE1.
Trigger checks if TABLE1.StatusOfPosting changed to some value and depending on result updates TABLE2.DocumentStatus.
Depending on bussienes logic, maybe you will need and BEFORE DELETE trigger.
CREATE TRIGGER T1 FOR TABLE1 AFTER UPDATE POSITION 0
AS
BEGIN
IF (NEW.StatusOfPosting <> OLD.StatusOfPosting and NEW.StatusOfPosting=1) THEN
UPDATE TABLE2
SET TABLE2.DocumentStatus=1
WHERE TABLE2.UniqueNumber = TABLE1.UniqueNumber;
END

Trigger: How does the inserted table work? How to access its rows?

I have the following table
Data --Table name
ID -- Identity column
PCode -- Postal Code
I created the following trigger:
CREATE TRIGGER Trig
ON Data
FOR INSERT
AS
BEGIN
Select * from inserted
END
And inserted the following values
INSERT INTO Data VALUES (125)
INSERT INTO Data VALUES (126)
INSERT INTO Data VALUES (127)
It shows this:
But I was expecting something like this:
After the 1st insertion, the trigger is executed -> one row is shown in the inserted table.
After the 2nd insertion, the trigger is executed -> two rows are shown in the inserted table.
After the 3rd insertion, the trigger is executed -> three rows are shown in the inserted table.
According to msdn.microsoft all the rows inserted are in this table.
How can I access the inserted table so that I can see all the expected rows and not separately?
You can not. From the Use the inserted and deleted Tables article on microsoft.com, you can read:
The inserted table stores copies of the affected rows during INSERT and UPDATE statements.
That means that the inserted table will only contain rows for the current INSERT or UPDATE statement.
If you do want to see all rows for several such INSERT or UPDATE statements, you will have to store these rows in a table you created yourself.
There are 2 table available in a trigger, the inserted and the deleted. Each update on table XXX is actually a delete row X from XXX then an insert of row X in table XXX. So the inserted inside the trigger is a copy of what got inserted. You can do a lot with a trigger, but triggers are dangerous.
For example, on a performance gig, I found a huge SP being run by a trigger, we dropped it and the database came back online. Or another example, if you do a trigger wrong to audit logins, you can down the server.
As TT mentioned, if you want to see all the inserted records then you need to change your Trigger to something like this:
CREATE TRIGGER Trig
ON Data
FOR INSERT
AS
BEGIN
Select * into "tablename"
from
(Select * from inserted) Ins
END

Does my trigger updates all the records

I have written a simple trigger which sets a column value with the id column value.
This is my trigger.
CREATE TRIGGER SubSectionsPrioritytrigger
ON SubSections
AFTER INSERT
AS
UPDATE dbo.SubSections
SET Priority = Id
After writing this trigger that, does this updates all the records after each insert. Or the only created new row.
Could some one provide any info on this.
Thanks.
To Update just the inserted row, you can do this:
UPDATE dbo.SubSections
SET SubSections.Priority = SubSections.Id
FROM INSERTED
WHERE INSERTED.Id = dbo.SubSections.Id
It does exactly what you wrote
UPDATE dbo.SubSections
SET Priority = Id
Any row will be updated.
You can change this to
UPDATE dbo.SubSections
SET SubSections.Priority = Inserted.Id
FROM INSERTED
WHERE INSERTED.id = SubSections.id
this will affect only the inserted rows.
to update just the last inserted row to what ever value you want you need to specify that row id which makes that row unique, from other rows.
and in your trigger you have not specified a where clause which causes all rows in the table to be updated.
whenever a any operation/event occurs on the table which has trigger associated with it mean a new record is inserted/updated or deleted an magic table is created in memory of SQL Server and we can access that magic table with the keyword "Inserted" in case of insert or Update and "Deleted" in case of delete.
so your query should be like this.
UPDATE dbo.SubSections
SET SubSections.Priority = SubSections.Id
FROM INSERTED
WHERE INSERTED.Id = dbo.SubSections.Id

SQL Server insert trigger not working

This is my first time using triggers.
My trigger is not being triggered please help.
CREATE TRIGGER sbhack_autoban
ON LOG_CONNECT201211
FOR INSERT
AS
BEGIN
/* query to run if single or multiple data is
inserted into LOG_CONNECT201211 table */
UPDATE login.dbo.USER_CHECK_LOGIN
SET login.dbo.USER_CHECK_LOGIN.CHECKLOGIN = 2
WHERE login.dbo.USER_CHECK_LOGIN.USER_KEY IN
(SELECT e.USER_KEY
FROM game.dbo.CHAR_DATA0 AS e
INNER JOIN gamelogs.dbo.LOG_USING_DEPOT201211 AS p
ON e.CHAR_KEY = p.CHAR_KEY
WHERE p.GATENUM = 150)
AND login.dbo.USER_CHECK_LOGIN.CHECKLOGIN = 0
AND login.dbo.USER_CHECK_LOGIN.USER_KEY != 51;
END
This is suppose to run the query inside the BEGIN : END if an entry is inserted into the LOG_CONNECT201211 table. But nothing is happening even when I have inserted multiple data into LOG_CONNECT201211.
When your INSERT trigger fires - then at least one new row has been inserted! That's a fact.
Now the question is: given that a single or multiple new rows have been inserted - what do you want to do with this knowledge??
Typically, you could e.g. set a column to a value you cannot specify as a default constraint - or you could insert the fact that the row has been inserted into an audit table or something....
So you'd have something like this:
CREATE TRIGGER sbhack_autoban
ON LOG_CONNECT201211
FOR INSERT
AS
INSERT INTO LogAudit(InsertedDate, UserKey)
SELECT
GETDATE(), i.User_Key
FROM
Inserted i
or something like that....
Update: ok, so you want to run that UPDATE statement when the rows have been inserted - not 100% clear, what columns/values from the inserted rows you want to use - looks like the e.UserKey column only - correct?
Then the UPDATE would be:
UPDATE login.dbo.USER_CHECK_LOGIN
SET login.dbo.USER_CHECK_LOGIN.CHECKLOGIN = 2
WHERE
login.dbo.USER_CHECK_LOGIN.USER_KEY IN
(SELECT USER_KEY FROM Inserted)
AND login.dbo.USER_CHECK_LOGIN.CHECKLOGIN = 0
AND login.dbo.USER_CHECK_LOGIN.USER_KEY != 51;
Update #2:
The point I still don't understand is : why do you want to run an update that uses the USER_CHECK_LOGIN, CHAR_DATA0 and LOG_USING_DEPOT201211 tables, when some rows are getting inserted into a totally separate, unrelated table LOG_CONNECT201211 ??
A trigger is used when you want to do something because rows have been inserted into that table - but in that case, you typically want to do something with the rows and their values that have been inserted...
I just don't see any connection between the rows being inserted into LOG_CONNECT201211 event, and the tables you are then querying from and updating. Where's the link?? WHY do you need to run *this UPDATE when data is inserted into LOG_CONNECT201211 ?? It would make sense if data where inserted into one of the tables involved in the UPDATE - but like this, it just totally doesn't make any sense .....

How to check if a column is being updated in an INSTEAD OF UPDATE Trigger

I am making some tweaks to a legacy application built on SQL Server 2000, needless to say I only want to do the absolute minimum in the fear that it may just all fall apart.
I have a large table of users, tbUsers, with a BIT flag for IsDeleted. I want to archive off all current and future IsDeleted = 1 user records into my archive table tbDeletedUsers.
Moving the currently deleted users is straight forward, however I want a way to move any future users where the IsDeleted flag is set. I could use a standard AFTER trigger on the column however I plan to add some constraints to the tbUser table that would violate this, what I'd like is for my INSTEAD OF UPDATE trigger to fire and move the record to archive table instead?
I guess my question is... is it possible to trigger an INSTEAD OF UPDATE trigger on the update of an individual column? This is what I have so far:
CREATE TRIGGER trg_ArchiveUsers
INSTEAD OF UPDATE ON tbUsers
AS
BEGIN
...
END
GO
If so an example (SQL 2000 compatible) would be much appreciated!
Using the UPDATE(columnname) test, you can check in a trigger whether a specific column was updated (and then take specific actions), but you can't have a trigger fire only on the update of a specific column. It will fire as soon as the update is performed, regardless of the fact which column was the target of the update.
So, if you think you have to use an INSTEAD OF UPDATE trigger, you'll need to implement two kinds of actions in it:
1) insert into tbDeletedUsers + delete from tbUsers – when IsDeleted is updated (or, more exactly, updated and set to 1);
2) update tbUsers normally – when IsDeleted is not updated (or updated but not set to 1).
Because more than one row can be updated with a single UPDATE instruction, you might also need to take into account that some rows might have IsDeleted set to 1 and others not.
I'm not a big fan of INSTEAD OF triggers, but if I really had to use one for a task like yours, I might omit the UPDATE() test and implement the trigger like this:
CREATE TRIGGER trg_ArchiveUsers
ON tbUsers
INSTEAD OF UPDATE
AS
BEGIN
UPDATE tbUsers
SET
column = INSERTED.column,
…
FROM INSERTED
WHERE INSERTED.key = tbUsers.key
AND INSERTED.IsDeleted = 0
;
DELETE FROM tbUsers
FROM INSERTED
WHERE INSERTED.key = tbUsers.key
AND INSERTED.IsDeleted = 1
;
INSERT INTO tbDeletedUsers (columns)
SELECT columns
FROM INSERTED
WHERE IsDeleted = 1
;
END