If I have a statement
that updates multiple rows, only the trigger will fire only on the first or last row that is being updated (not sure which one). I need to make a trigger that fires for ALL the records that are being updated into a particular table
Assuming SQL Server, A trigger only fires once per update, regardless of the number of rows that are updated. If you need to carry out some additional logic based on updates to multiple rows you can access the changed records by looking at the INSERTED and DELETED logical tables that are accessible in the context of a trigger.
You have not specified the database .....
In Oracle a trigger can be defined to fire for individual rows and based on the type of transaction:
CREATE OR REPLACE TRIGGER BIUDR_MY_TABLE
BEFORE INSERT OR UPDATE OR DELETE
ON MY_TABLE
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
pk PLS_INTEGER;
BEGIN
etc ....
You just need to indicate if your trigger needs to be executed "FOR EACH ROW" or "FOR EACH STATEMENT". Adding one of these two clauses in the trigger definition will tell the DBMS when to execute the trigger (most, but not all, DBMSs support it). If you don't indicate this clause then the DBMS uses the default option which in your case seems to be the FOR EACH STATEMENT option, and that's why your trigger only fires one for each update sentence, regardless of how many rows you are updating
Related
I'm having a little trouble with understanding functions and triggers in sql. I didn't post the code of procedure chkInsertAritcle but let's say it returns NEW if it managed to make change and NULL if it didn't.
So my question is about the trigger. If I put AFTER INSERT does that means that it will complete INSERT without depending on the return value? And what
happens with the rest of the rows?
Next question is if I put BEFORE INSERT, in what order does code runs?
Thanks!
CREATE TRIGGER ArticleIns
AFTER INSERT ON ListOfArticles
FOR EACH ROW
EXECUTE PROCEDURE chkInsertArticle();
First all BEFORE triggers run in alphabetical order, then the operation is performed, then all AFTER triggers run in alphabetical order.
Each operation sees the result of the previous one as input, and if any trigger returns NULL, processing for that row stops. So if a BEFORE trigger returns NULL, the DML operation won't take place.
This happens independently for each row affected by the triggering DML statement.
So if the trigger runs before insert, then the code runs before the data is inserted into the row and constraints are checked. So for example you might want to add a timestamp before the data is committed to the database,
If it runs after then the data is already present in the table and all constraints have been checked. This is usually where you want to trigger another process based on the row data, maybe update another table, send an e-mail etc.
In your example, the data will be in the database before your procedure runs. So if your procedure modifies the row data, it needs to be in the database.
I'm trying to get a reference to a set of rows that I'm trying to insert into a table through a multiple insert. For example if I execute:
INSERT INTO T VALUES (0,'A'),(1,'B'),(2,'C')
I would like to get a reference in a before insert trigger to a "table" that contains these 3 rows. Is that possible?
And another question: what does a REFERENCING NEW_TABLE represents in a before trigger (maybe could this be the answer to the first question)?
Thanks
According to documentation:
REFERENCING NEW TABLE AS identifier
Specifies a temporary table name which identifies the affected rows as modified by the triggering SQL operation and by any SET
statement in a BEFORE trigger that has already executed.
Also take a look:
FOR EACH STATEMENT
Specifies that the triggered action is to be applied only once for the whole statement. This type of trigger granularity cannot be
specified for a BEFORE trigger or an INSTEAD OF trigger (SQLSTATE
42613). If specified, an UPDATE or DELETE trigger is activated, even
if no rows are affected by the triggering UPDATE or DELETE statement.
maybe it will suite better your needs (of course you need to go with AFTER trigger)
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 an update trigger for a table. When I am updating the table rows I need to check certain condition in trigger then based on that I want to update another column.
Is it possible?
You might want to read the documentation for CREATE TRIGGER, especially the remarks section, which includes:
If an INSTEAD OF trigger defined on a table executes a statement against the table that would ordinarily fire the INSTEAD OF trigger again, the trigger is not called recursively. Instead, the statement is processed as if the table had no INSTEAD OF trigger and starts the chain of constraint operations and AFTER trigger executions.
If this, or other parts of the remarks section, don't answer your questions, you probably need to add more to your question about what problems you're having, or what issues you're concerned about.
I rarely write triggers. I can use help setting up the thing.
CREATE TRIGGER audit_tableName
ON dbo.tableNameAudit
AFTER CREATE, UPDATE, DELETE on tableName
AS
BEGIN
--Get Created,updated,deletes items
INSERT into dbo.tableNameAudit(columns) VALUES ([allCUDitems])
END
GO
How do I get an iterate any CREATED, UPDATED, DELETED items that caused the trigger?
check out this msdn article.
the short of it are there are 2 special tables, inserted and deleted, that are accessible in your trigger. inserted will contain updated rows and inserted rows, while deleted will contain updated rows and deleted rows.
make sure that you understand that for a batch operation a trigger is only fired one time, so be sure to handle the possibility of multiple rows being present in those tables.
Triggers have access to two pseudo tables: INSERTED and DELETED. As their name suggests, these pseudo tables will contain all the values added or removed from the table. An update will cause a row in each of the pseudo-tables. The structure of these pseudo-tables is identical with the structure of the table on which the table is declared.
In addition the UPDATE() function inside a trigger will return TRUE for columns that were updated.
You can use INSERTED.[COLUMN] OR
SELECT [COLUMN]
FROM INSERTED
This on SQL Server.
Hope it helps.