I'm planning to install a trigger on a table which is executed after every statement (foreach-statement).
But I'm not sure what statement exactly means. For example, if I do multiple inserts in one transaction, for example 1,000.
Will the trigger then be executed one time for a thousand times?
Related
I need to know about how the trigger execution happens for the below scenario.
I have 20 records in a table and I have an AFTER INSERT, UPDATE trigger on that table. When I'm updating all the records in that table using a MERGE or batch update statement, how will the trigger execute?
Does it execute for each row by row?
Or is it executing once per a batch (once for all 20 records)?
If it is execute once per batch do we need to write a loop inside the trigger to perform a task for each row?
Triggers in SQL Server always execute once per batch - there's no option for "for each row" triggers in SQL Server.
When you mass-update your table, the trigger will receive all the updated rows at once in the inserted and deleted pseudo tables and needs to deal with them accordingly - as a set of data - not a single row
Refer to my previous posting.
Sql Cleanup script, delete from one table that's not in the other1
Using DB2 for IBM i (As400, Db2).
I am executing the following sql as a cleanup script 3am.
DELETE FROM p6prodpf A WHERE (0 = (SELECT COUNT(*) FROM P6OPIPF B WHERE B.OPIID = A.OPIID))
I have a different process that at the same time that this sql runs inserts two records, the first record is the P6OPIPF record and then inserts the detail record into P6PRODPF.
The problem.
The P6PRODPF record is missing after the SQL cleanup ran. But remember that the process that stores the records ran the same time.
How I understand the SQL is that it go's through P6PRODPF and checks if the record is in P6OPIPF if its not in P6OPIPF then delete P6PRODPF.
But then I ran Visual Explain in I systems navigator on this SQL and got the following result.
Now I am confused.
After Visual explain It looks like the statement starts with checking P6OPIPF.
So then it reads: If there's a record in that instance of time in P6OPIPF and no record with the same key in P6PRODPF then delete the P6PRODPF.
This could explain my problem that P6PRODPF gets deleted when my process that inserts the records and the sql script runs at the same time.
So how I see it in Sequence.(My theory)
The process that inserts the two records starts.
The process that inserts the two records inserts the first record in
P6OPIPF.
At the same time the SQL cleanup runs. the query see's the P6OPIPF
record and checks if it has a P6PRODPF record. At this stage
there is still no P6PRODPF inserted so Sql thinks it needs to
delete the record in P6PRODPF.
In the same time The process that inserts the two records inserts the
second record in P6PRODPF.
And because the Sql did not see the P6PRODPF at that stage it
deletes the new inserted record in P6PRODPF leaving a P6OPIPF
record with no P6PRODPF record.
Am I correct?
What I actually want to know is just the Delete script listed above. How I understand the SQL is that it go's through P6PRODPF and checks if the record is in P6OPIPF if its not in P6OPIPF then delete P6PRODPF. But after the visual explain I can see its starts with checking P6OPIPF. So What will the delete statement first check?
The code of the insert is generated in CA PLEX generator. RPGIV code.
My one function that will insert first P6OPIPF(OperationsItem.Update.InsertRow) and then its detail in P6PRODPF(ProductDetail.Update.InsertRow).
Insert Row function
My Scheduled function code that will execute the delete Script.
Scheduled delete script function
Hope it makes sense.
Visual Explain is a useful tool for understanding what the DB is doing, particularly when trying to enhance performance.
But SQL is not a procedural language. You should not nor can you really be trying to say when I run this statement, the DB is doing this, then it's doing this.
While it might be true for that particular run, it's highly dependent on the data and resources available. You can not code a processes around the steps you see.
You really shouldn't be trying to run both processes at the same time, there's simply no way to ensure what you'll end up with; at least when using the default isolation level (probably "no commit" or "read uncommited" depending on the interface.)
If you must run both processes at the same time, you probably want to run the delete under "repeatable read" or "serializable"; which should have the effect of locking the tables being referenced so that no other process can change them.
Optionally, you could run both the delete and insert under the read stability or higher isolation levels.
To explain the Visual Explain, DB2 will check the inner expression before executing the DELETE clause - it has to, or else it won't know what rows are affected.
The reason your archived rows aren't archived is because the delete script ran before the insert script.
Do you have heard of the concepts "transaction" and "isolation"? Typically different processes running against the same database are shielded (isolated) against each other, so they are operating without seeing the immediate impact of any other transaction running at the same time. Logically two transactions (a process or sequence of SQL statements) executed at the same time are executed in a serial way.
In your case either the first process is the "first" or "second". If you repeat your tests you may see different results depending on who is "first" (logically).
I have created a trigger and I want to stop the trigger from executing its code for some time. Is there any function available in oracle for this.
Being more specific:-
I have to perform an action when a PO is created in oracle apps.
I need to find requisition number for this po which I will get by joining distributions and lines table. But when trigger is fired there wont be any data in lines and distribution table.
alter trigger <trigger_name> disable;
then to enable
alter trigger <trigger_name> enable;
You cannot delay your trigger, it will fire as soon as you perform the event on the table.
There is no native database way to delay the trigger for some specified period of time.
In general you can enable or disable trigger using,
ALTER TRIGGER trigger_name ENABLE/DISABLE;
You can write this code in a stored procedure and then get it executed using some out-of-the-database program, e.g. PHP, JAVA, SHELL etc. (depending on your architecture) that supports time driven execution
DBMS_LOCK.SLEEP might to the trick:
http://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_lock.htm#ARPLS66781
You can easily delay an action by creating a job.
For example, your trigger may call DBMS_JOB.submit to create a job to run at a particular time (e.g. 10 minutes after the current time). The job needs to be created with the name of a procedure that needs to be run. For example, you might create a procedure that takes a record ID as a parameter.
The nice thing about DBMS_JOB is that it is transactional - so if your triggering statement is rolled back, the job will also be rolled back.
The downside is that the job will never start until after the statement that created it is committed.
I have a BEFORE DELETE trigger which inserts rows into another table using SPI_exec.
Do these INSERT queries run in the same transaction as the one in which the original delete is executing? Hence, will the delete and all inserts roll back or commit together?
If not, how can I make that happen?
Yes, everything in triggers is in the same transaction as the triggering event.
Not directly related to the question, but normally you want to put side-effects in the AFTER trigger, rather than the BEFORE trigger.
I have a table that has an insert trigger on it. If I insert in 6000 records into this table in one insert statement from a stored procedure, will the stored procedure return before the insert trigger completes?
Just to make sure that I'm thinking correctly, the trigger should only be called (i know 'called' isn't the right word) once because there was only 1 insert statement, right?
My main question is: will the sproc finish even if the trigger hasn't completed?
Your insert trigger will run once for the entire insert statement. This is why it is important to use the inserted temporary table to see what has actually been inserted, and not just select the most recent single record, or something like that.
I just tested an insert and update trigger and indeed, they are considered part of the insert by sql server. the process will not finish until the trigger finishes.
Triggers are part of the transaction that called them.
One important thing about triggers that you must be aware of is that the trigger fires once for each transaction (at least in SQL server, you should check other dbs, but even if it will process row by row, that is usually a poor idea), so if you insert 6000 records the trigger fires once not 6000 times. Many people are not aware of this and write triggers as if they will process multiple record inserts one record at a time. This is not true and your trigger must account for handing the multiple record insert.
The trigger call is not asynchronous. Each call to your insert procedure will result in the trigger being fired, and the procedure will not return until the trigger finishes.
Take a look at the query plan to see how it works. You'll see that the statements in the trigger will be called for each call to the procedure.
The thing is, every time the TRIGGER criteria is met, the TRIGGER fires. It fires once in batch processing or Transaction. See my lesson 101 on TRIGGER
You should use cursor in insert statement to process trigger row.
Because Triggers in SQL Server fire once per statement, not once per row.