The database I am using already has a 2 triggers on part number table (on insert and on update). Insert trigger updates creation date, and update trigger updates modification date.
I have to add 3 more triggers to log updates to this table (on insert, on update and on delete)
In what order they will be executed? Before existing trigger or after? Can I control that?
sp_settriggerorder will allow you to set first or last trigger.
If you have more than two and the order matters, combine them into one trigger and split the functionality over the stored procedures.
Related
is it possible to declare one Sql Trigger Insert, Update, Delete for all tables in the database instead of creating a separate trigger for each table? I just want a simple history of what actions have been taken e.g. TABLE A deletes a row ,TABLE B updates a row ,TABLE C Add new row .. and the trigger will insert a new row to another table with that information I want.
No, a trigger can only be defined on a specified table.
You should read up on the auditing features of SQL Server (http://technet.microsoft.com/en-us/library/cc280386.aspx). They are more performant and more flexible in what you want to achieve. Unfortunately they are not available in the Express Edition.
I have been trying to find out if I can make a column Open on Insert, and closed on Update.
What I mean by that, is I need a column that I can give it a value only on Insert, but if I try to give it a value with Update, the statement would fail.
I am working with SQL 2008...
You can't do this with constraints - you need to use triggers for this.
A trigger is a special kind of stored procedure that automatically executes when an event occurs in the database server. DML triggers execute when a user tries to modify data through a data manipulation language (DML) event. DML events are INSERT, UPDATE, or DELETE statements on a table or view.
I have created an on update trigger.
If I am updating 5 records in the table in a single statement, how many times will the trigger execute? Does it change if I have multiple statements updating the records in a single transaction?
Does it execute 5 times, or only once after all the transactions are complete?
It all depends on the type of trigger you are using.
a row level trigger will fire for each and every row that is affected by the DML statement (note this is also true for INSERT statements that are based on a SELECT or are using a multi-row syntax to insert more than one row at a time)
a statement level trigger will fire once for the whole statement.
Oracle, PostgreSQL and DB2 support both, row level and statement level triggers. Microsoft SQL Server only supports statement level triggers and MySQL only supports row level triggers.
With SQL 2008:
If you are doing 1 update that updates 5 rows, the trigger should be executed only once.
That's why you have to use the tables "INSERTED" and "DELETED" to be able to detect all the modified rows.
If you are doing 5 updates that update 1 row, the trigger will be executed 5 times.
Considering you are using SQL Server, the trigger will only fire once every Update.
If this is not what you want, you could consider using different update statements to make sure the trigger fires everytime.
You can look at this turorial on SQL triggers. It covers everything.
Note that if you are using Oracle the trigger can be based on rows. Not in SQL Server.
I need a sql statement, to insert a new row in one database table and update an existing row in another database table based on some conditions.
Is there a way to do this? To insert a row in one table and update a row in another database table in one sql statement?
Thanks in advance!
Yes, they are called Transactions, and are implemented with START TRANSACTION and COMMIT/ROLLBACK with something like:
START TRANSACTION;
INSERT INTO ...
UPDATE table2 SET name='TOTO' WHERE type=1;
COMMIT;
EDIT
This is not in fact one SQL query, but the operation is done atomically - and I think that is what you need.
A single SQL statement allows you to update one table, not several; if that statement is a MERGE then you can specify insert/update/delete actions but still targeting just the same one target table.
If you just want consistency, use transactions; until a transaction is committed, changes within it are not visible to the outside world.
If you want that a single update (which you cannot control) resulted in a coordinated insert, use an on update trigger in the table being updated. The trigger would insert appropriate row(s) into other table(s).
You can use Trigger to update second table on insert of first table
Yes, it's possible with stored procedures.
Watch this: Stored procedures
I have a couple of triggers in a Sybase ASE database that are fired upon updates to two tables: Docs and Trans.
The triggers are defined as shown here:
For Docs:
CREATE TRIGGER dbo.Index_Change_Docs
ON dbo.docs
FOR INSERT,UPDATE AS
IF UPDATE(DOCTYPE) OR UPDATE(BATCH_NO) OR UPDATE(SCANDATE) OR
UPDATE(PERIOD_START_DATE) OR UPDATE(PERIOD_END_DATE)
OR UPDATE(DISPATCH_ID) OR UPDATE(DISPATCH_NAME) OR UPDATE(CHECKNUM) OR
UPDATE(CHECKAMT)
BEGIN
INSERT INTO
DOCID_SYNC (IS_DOC_ID, CRTN_DT, SYNC_STATUS_CDE)
SELECT Inserted.DOCID, GETDATE(), "N" FROM Inserted
END
For Trans:
CREATE TRIGGER dbo.Index_Change_Trans
ON dbo.Trans
FOR INSERT,UPDATE AS
IF UPDATE(TRANSNUM) OR UPDATE(CONTRACT) OR UPDATE(FRANCHISE) OR UPDATE(SSN) OR
UPDATE(STATE_CODE) OR UPDATE(TRANSTYPE)
OR UPDATE(AGENCYNUM) OR UPDATE(LOCKBOXBATCHNUM) OR UPDATE(PRODUCTCODE)
BEGIN
INSERT INTO
DOCID_SYNC (IS_DOC_ID, CRTN_DT, SYNC_STATUS_CDE)
SELECT DOCID, GETDATE(), "N" FROM DOCS
WHERE Transnum = (SELECT Inserted.TransNum from Inserted)
END
It appears the behavior of these triggers is different, depending on how updates to those tables are made.
In one case, these tables are updated via two stored procedures (Insert_Docs_SP and Insert_Trans_SP). When this happens, each trigger is fired once (once for Docs, one for Trans) and everything works as expected.
In another case, these tables are updated within a Sybase transaction with two database updates. Here, the first update is done via inline SQL in the calling application (which fires the Trans trigger.) The second update is done via a stored procedure - Insert_Docs_SP, the same as in the other case - which does not fire a trigger.
Perhaps there is something about how transactions are handled that I am not understanding?
In both of your triggers, the trigger is only inserting into docid_sync table if certain columns are updated. Are you sure that the stored procedure is updating one of the columns in the trigger? Triggers are also not called if it is a recursive update from a trigger call, but that doesn't seem to be the case here.
The other possibility is if the calling transaction disabled the trigger with the set triggers off command. I would start with ensuring that the stored procedure is updating one of the columns in the trigger checks.
One other question: Is the same row being updated twice, in the inline SQL And stored procedure in your error case, or are they updating two different rows?
I found the answer - it's in the order of execution. I thought one of the triggers wasn't being fired - in this case the Index_Change_Trans trigger - but in fact it was. I didn't see the results, however, because this trigger is relying on entries in the Docs table.
INSERT INTO
DOCID_SYNC (IS_DOC_ID, CRTN_DT, SYNC_STATUS_CDE)
SELECT DOCID, GETDATE(), "N" FROM DOCS
WHERE Transnum = (SELECT Inserted.TransNum from Inserted)
So, in cases where the Trans table was updated before the Docs table, the run of the Trans trigger would not show an update in the Docid_Sync table - since at this point there were no entries in the Docs table with the appropriate Transnum value. In these cases, the Docid_Sync table only has one entry, the result of the Docs trigger.
In other instances, the Docs table is updated first, and then the Trans table. In these instances, the Docid_Sync table has two entries - one as the result of the Docs trigger, and another as the result of the Trans trigger.