DB: MySQL
Using: MySQL Workbench
I am currently working on a project for class where we have to design a airport website in which users can login/register and buy tickets for various flights offered. After working on the project for some time I realized that my trigger is not working.
I receive the error: Error Code: 1442. Can't update table 'reservation' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
I stumbled upon this error by trying to insert a reservation before creating the form for users to select and buy tickets. I was wondering if someone could take a look at my database, insert command use, and also my trigger code. Any help would be much appreciated because I am at wits end trying to figure this out for hours.
Insert command: http://pastebin.com/tyBPWNDd
Entire DB and Trigger in question: http://pastebin.com/BvUj1NdH
Solved: thanks to all helpers I was able to identify my problem which was using recursive triggers when MySQL does not support them. I solved my problem by removing the recursive code and letting my website backend handle the current_date set instead of the trigger. I will post the fixed trigger shortly.
Yes, the error is self explanatory. You are trying to create a recursive trigger which is not supported in MySQL as can be seen in your posted code
Create Trigger reservation_all
after insert on Reservation
for each row
begin
update Reservation
Check MySQL Documentation on same for more infromation. Quoting from that
Stored functions cannot be used recursively.
A stored function or trigger cannot modify a table that is already being used (for reading or writing) by the statement that invoked the
function or trigger.
Related
Working on a security DDL trigger for a database and want to restrict non-admins from creating/dropping database, I have created this trigger and put it below all the other code (create tables etc) in the database script.
CREATE TRIGGER alert_table
ON DATABASE
FOR CREATE_TABLE, DROP_TABLE, ALTER_TABLE
AS
BEGIN
IF IS_MEMBER ('admin') = 0
BEGIN
PRINT 'Please contact your Database Admin'
ROLLBACK TRANSACTION;
END
END
GO
CREATE
Note:
USER 'admin'#'localhost'
It says "ON is not valid at that position, expecting: BEFORE or AFTER", and something similar for "END". Thanks!
You followed a tutorial for Microsoft SQL Server, commonly abbreviated as mssql server, while you are using mysql.
Mssql server has DDL triggers which syntax follows the one in your question.
Mysql's create trigger syntax is different and does not have DDL triggers at all, so you cannot use triggers to handle table creation events.
i'm working on a proyect in mysql and i can't made things work between 2 triggers, what i'm trying to do is
1)
Create a trigger that after inserting values in a table update the data of another table, working
2)
Create a trigger that after updating the aforementioned table, delete the row that detonated the first trigger, not working
I searched the documentation, examples, tutorials, goolge and of course in different posts of the site, but I have not found anything that can guide me or help to solve my problem :(
For the moment i have this
1)
CREATE TRIGGER update1 BEFORE INSERT ON table1
FOR EACH ROW
UPDATE table2 SET table2.value = table2.value +
NEW.value WHERE ac_id = NEW.acc_id
2)
CREATE TRIGGER `delete` AFTER UPDATE ON table2
FOR EACH ROW DELETE FROM table1 WHERE table1.acco_id =
NEW.acc_id
Individually both work, but if I make an insert in table1 the following message appears
Can't update table 'table1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
sorry for my bad English, any help will be highly appreciated, thanks in advance
The observed error message:
ERROR 2442 (HY000) Can't update table '%s' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
is expected behavior. The triggers shown in the question violate a documented restriction:
A stored function or trigger cannot modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger.
Reference: https://dev.mysql.com/doc/refman/5.7/en/stored-program-restrictions.html
To focus that on the specific triggers shown in the question, in the context of a trigger fired by an insert into table1, it is not possible to delete rows from table1. There is no workaround to this restriction.
To "solve this problem" means to step back from the current design, and come up with a different design which achieves the objectives.
I'm trying to create a trigger to delete my IP from my internal app (as a dev half of the logs are mine) to keep the log cleaner. To do that I constantly go and query manually in phpMyAdmin:
DELETE FROM `log` WHERE `ip1` = "xxx.xxx.xxx.xxx";
I tried creating a trigger in phpMyAdmin with that code but I keep getting the syntax error. I tried with both old. and new., also before and after, nothing works I get this error:
Error: SQLSTATE[HY000]: General error: 1442 Can't update table 'log' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
(the trigger is accepted in phpMyAdmin but when I access the app I get that).
As I read the reason it's because you can't use delete on a insert trigger, because the table gets locked in the first place, etc., but I don't find any way around it to achieve what it seemed to me like a simple task... sorry my knowledge on MySQL is quite limited. Surely there must be a way...
I have a stored procedure which basically selects data from one table and insert into another table. Basically I am doing data archiving manually. Now, I want to write an event just like discussed here
However, after reading that post and researching online, I came to know that it's not possible to create an event inside a stored procedure. Is there a way to accomplish my goal in MySQLWorkbench?
I believe you are thinking this in the oposite direction: You can't create an event in a stored procedure, but you can create a stored procedure and call it from an event.
Example:
delimiter $$
create procedure myProc()
-- Dummy procedure to move the data from mainTable to backupTable,
-- and then clear (truncate) mainTable
begin
insert into backupTable select * from mainTable;
truncate mainTable;
end $$
delimiter ;
-- Now, suposing that you want to execute this procedure every hour:
delimiter $$
create event myEvent
on schedule every 1 hour
do
begin
call myProc();
end $$
delimiter ;
You can write this as any other query in the workbench, or directly in the command line client.
About your concern
After reading your comment, I believe you are a bit confused about what MySQL Workbench is.
MySQL Workbench is only a graphical application that allows you to connect to a MySQL server and perform queries and administration tasks. But Workbench is not the core of MySQL... it is only a viewer (with steroids, maybe, but a viewer after all).
Now, the event scheduler does not reside in Workbench, but in the MySQL server instance you are connecting to. Just as the tables, views, procedures and functions are not stored in the Workbench interface but in the server, the events are also stored in the server.
(Yes, I believe it is a relevant SNAFU that the scheduled events don't show anywhere in the graphical interface, but... after a while, one learns to live with that kind of frustrations and to move on with life)
Maybe your only concern is: "Hey, and what if I want to know what events are set to run in the event scheduler?" You can execute a "show events" query to show a list of the events in the current database, and you can execute "show create event yourEvent" to show the create event syntax for that event.
I insist: Read the manual, and keep a copy at hand (download the manual for your MySQL version here).
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.