I have created a trigger for a table in SQL Server 2008
CREATE TRIGGER trigger_mytable
ON dbo.mytable
FOR INSERT, DELETE, UPDATE
AS
EXTERNAL NAME mycode.[trig.mytable].myfn
The code for mytable.myfn is in C#. It opens a connection to the database and queries the inserted or deleted table based on the event to get the trigger data. Can it be possible that an entry is inserted and immediately deleted (in like a fraction of a second or say ms) from the table and the trigger function is never called? In short can there be a latency or absence of trigger? My understanding is that triggers use interrupt sort of mechanism rather than polling. I am very new to SQL Server and triggers.
No: there is no latency or lag
The trigger is part of the INSERT and DELETE statement. When the trigger completes, then SQL Server reports the INSERT or DELETE as complete
Note: you'd typically keep triggers short and concise and not use external code or calls
Related
My use case is that I have a MYSQL table which has a change tracking table behind it. Both tables are InnoDB.
I'd like to use triggers to enforce two things.
One: forcing a copy to be made of previous state on every update (update trigger performs insert select query) This is non-trivial and I have already done it.
Two: limit access to the second table to read only for users, while triggers can still insert/update/delete as necessary
Further research on user access and triggers has dug up this:
Mysql 5.5 reference manual: 19.6 Access Control for Stored Programs and Views
Turns out that stored programs can be assigned a user to run as. Triggers are stored programs. By restricting Insert, Update, and Delete to a special user which only will be used by a trigger and using the DEFINER attribute of the trigger (or any stored program) I can make the trigger which I want to have access run under that user.
In SQL Server 2008, let's say I have a table with a view and INSTEAD OF triggers on it.
When I insert or update, is there a way inside the trigger to determine the SQL query that was used to invoke the trigger?
For example, if I do the following:
UPDATE MyView SET Address = '123 Main St'
Is there a way inside the trigger to get the actual SQL query that was used, i.e.,
UPDATE MyView SET Address = '123 Main St'
I hope this makes sense.
Thanks.
No, the trigger isn't invoked by that statement - the triggers is fired from the RDBMS because the condition it's defined for (INSERT, UPDATE or DELETE) has occurred.
The trigger is totally asynchronous from the actual statement, and no, you cannot get the T-SQL query that caused the trigger to fire. All you can rely on are the Inserted and Deleted pseudo tables that are available inside the trigger which tell you what rows were inserted, deleted, updated.
Are special variables like TG_OP TG_TABLE_NAME (as in postgresql) available in MySQL, if not then is it possible to know for which operation (INSERT, UPDATE etc) the trigger was fired?
Mysql defines different triggers for different operations. For Example there would be a trigger for BEFORE INSERT so you would know that insert operation fired the trigger, or there could be a trigger for AFTER UPDATE so you know update caused the trigger to be fired.
Read the tutorials below for having a detailed look on mysql triggers.
http://www.mysqltutorial.org/mysql-trigger-implementation.aspx
http://blog.cnizz.com/2010/11/12/mysql-trigger-how-to-example-tutorial-and-syntax/
I have trigger on a table which is written longtime back and can’t retire or modify at this moment. There are lot of select statements are there which get fired irrespective of any condition in this trigger.
Now I have another Stored Procedure which will update the two columns in the above mentioned table and I don’t want any other operation or any queries which were written in the trigger needs to be fired when this operation ( calling SP) is performed.
So I though before I call the update statement in this stored procedure, I disable the update trigger on this table and once I done with update statement will again enable the trigger .
Is this is good idea ? Any issues with this approach? I will do this operation in transaction so that if anything goes wrong , it will come back to original stage .
You can disable/enable a trigger by hand.
It is a good idea, as long as you are sure that the trigger does not update some other field or table and if no other job launching that trigger may run at the same time.
Problem: I've got a table which holds certain records. After the insert has been done, I want to call an external program (php script) via MySQL's sys_* UDFs.
Now, the issue - the trigger I have passes the ID of the record to the script.
When I try to pull the data out via the script, I get 0 rows.
During my own testing, I came to a conclusion that the trigger invokes the php script and passes the parameters BEFORE the actual insert occured, thus I get no records for given ID.
I've tested this on MySQL 5.0.75 and 5.1.41 (Ubuntu OS).
I can confirm that parameters get passed to the script before actual insert happens because I've added sleep(2); to my php script and I've gotten the data correctly.
Without sleep(); statement, I'm receiving 0 records for given ID.
My question is - how to fix this problem without having to hardcode some sort of delay within the php script?
I don't have the liberty of assuming that 2 seconds (or 10 seconds) will be sufficient delay, so I want everything to flow "naturally", when one command finishes - the other gets executed.
I assumed that if the trigger is of type AFTER INSERT, everything within the body of the trigger will get executed after MySQL actually inserts the data.
Table layout:
CREATE TABLE test (
id int not null auto_increment PRIMARY KEY,
random_data varchar(255) not null
);
Trigger layout:
DELIMITER $$
CREATE TRIGGER `test_after_insert` AFTER INSERT ON `test`
FOR EACH ROW BEGIN
SET #exec_var = sys_exec(CONCAT('php /var/www/xyz/servers/dispatcher.php ', NEW.id));
END;
$$
DELIMITER ;
Disclaimer: I know the security issues when using sys_exec function, my problem is that the MySQL doesn't insert FIRST and THEN call the script with necessary parameters.
If anyone can shed some light on how to fix this or has a different approach that doesn't involve SELECT INTO OUTFILE and using FAM - I'd be very grateful. Thanks in advance.
Even if you use an AFTER trigger, the row isn't committed yet. But sys_exec() doesn't return until the php script exits, so the AFTER trigger can't complete, therefore you can't commit the INSERT either.
This is by design. After all, you may do more operations within the same transaction, or you may roll back the transaction. That's the problem with invoking external processes from a trigger: external processes can't see data within the scope of the transaction in the database.
You shouldn't do this task with a trigger. At best, you should use the trigger to set a "flag" column and then write an external process to look for rows with the flag set and then invoke that PHP script. That way only rows that have successfully been inserted AND committed will be processed.
If I understand it clearly, you insert a row in your DB. That invoke a trigger that launch an external command written in PHP. That command queries in its turn the same DB by using the id of the inserted row?
I don't think this is a problem of "delay".
The real "problem" is your initial insert and you external command connect to the same DB on two different sessions -- probably in two different transactions (depending your database engine and your transaction isolation level).
I assume, when the trigger in invoked the row insert is not yet committed to the DB. So the external command still see the DB as it was before.
BTW, if the above explanation is quite speculative -- what is more evident to me is that you should probably think about a different design than trying to made that work as it is.