I am trying to run a small trigger with following query in Mysql :
create trigger sample_trigger after delete on my_network
for each row
begin
update (select active from my_network_ref where id=old.rid limit 1) vnetr set vnetr.active=0;
end;
After running these trigger in MySQL Workbench , i ma getting following error
Operation failed: There was an error while applying the SQL script to the database.
ERROR 1288: The target table vnetr of the UPDATE is not updatable
SQL Statement:
CREATE DEFINER = CURRENT_USER TRIGGER `mam_db`.`sample_trigger ` AFTER DELETE ON `my_network` FOR EACH ROW
BEGIN
update (select active from my_network_ref where id=old.rid limit 1) vnetr set vnetr.active=0;
END
Any syntax error or structural problems ? Please help
In MySQL, you cannot update a subquery. Instead:
update my_network_ref
set active = 0
where id = old.rid
limit 1;
Normally, you would use order by when using limit.
Related
I'm trying to create a trigger whereby an insertion on one table updates another. This is my SQL Query:
CREATE TRIGGER makePayment AFTER INSERT ON Payments FOR EACH ROW
BEGIN
UPDATE Invoice
SET InvoiceClientPaid = SUM(InvoiceClientPaid + NEW.PaymentAmt)
WHERE InvoiceID = NEW.PaymentInvoiceID;
END;
No matter what I do I get the following error:
Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 6
I don't think it's related to the SUM, because trying a basic = 1 on the SET command gives me the exact error. There is no '' at line 6 which is very confusing?
If you're entering this query directly into MySQL you will need to change the delimiter prior to the query using (e.g.) DELIMITER //, otherwise it thinks the query ends at the ; at the end of your UPDATE statement. MySQL then sees an END with nothing before it and complains about the nothing (''). So try this:
DELIMITER //
CREATE TRIGGER makePayment AFTER INSERT ON Payments FOR EACH ROW
BEGIN
UPDATE Invoice
SET InvoiceClientPaid = SUM(InvoiceClientPaid + NEW.PaymentAmt)
WHERE InvoiceID = NEW.PaymentInvoiceID;
END; //
DELIMITER ;
I'm trying to execute this query in a database through phpmyadmin
create trigger avoid_duplicated_sharing
before insert on sharingevents
for each row
begin
if ( select count(*) from sharingevents where shared_note_id = NEW.shared_note_id AND shared_to = NEW.shared_to > 0 ) then
delete from sharingevents where shared_note_id = NEW.shared_note AND shared_to = NEW.shared_to
END IF;
END
But phpmyadmin gives me the following error:
MySQL said: #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'END IF' at line 7
Two questions:
What's wrong with my script?
After a BEFORE INSERT trigger, Will INSERT operation be performed? In case it doesn't I will have to remove INSERT INTO SharingEvents (SELECT * FROM NEW);
I solve it with the following code:
delimiter $$
create trigger avoid_duplicated_sharing
before insert on sharingevents
for each row
begin
if ( select count(*) from sharingevents where shared_note_id = NEW.shared_note_id AND shared_to = NEW.shared_to > 0 ) then
delete from sharingevents where shared_note_id = NEW.shared_note_id AND shared_to = NEW.shared_to;
end if;
END$$
The problem was the delimiter.
Even so, my trigger doesn't work. When the application inserts duplicated primary keys MySQL throws the following error:
#1442 - Can't update table 'sharingevents' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
Use exists:
if (exists (select 1 from sharingevents where shared_note_id = new.shared_note_id AND shared_to = new.shared_to) > 0) then
insert into sharingevents (shared_note_id,shared_to,permission_level)
values (NEW.shared_note_id,NEW.shared_to,NEW.permission_level);
end if;
Or, better yet, add a unique index on sharingevents(shared_note-id, shared_to) and then use:
insert into sharingevents (shared_note_id, shared_to, permission_level)
values (NEW.shared_note_id, NEW.shared_to, NEW.permission_level)
on duplicate key update shared_note_id = values(shared_note_id);
This will ignore any updates where the pairs already exist in the table. No if required.
count(shared_note_id, shared_to) is invalid syntax. You can only put multiple column names inside COUNT() when you use count(DISTINCT ...). In your case, you don't need to put column names at all, just use COUNT(*) to count the number of rows matching the condition.
See count(*) and count(column_name), what's the diff? for more information about when you should put column names in COUNT()
Unfortunately, fixing the syntax errors won't really solve your problem, because you can't use a trigger to make a change to the same table. From the FAQ:
Can triggers access tables?
A trigger can access both old and new data in its own table. A trigger can also affect other tables, but it is not permitted to modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger.
You'll need to recode the callers to use INSERT ... ON DUPLICATE KEY UPDATE, or something equivalent, to accomplish this.
I am trying to get the quantity field synchronized in 2 tables on 2 different databases using triggers.
I found some examples and tried to adapt them to this requirement why not success and showing this error...
#1442 - Can't update table 'oc_product' in stored function/trigger because it is already used by statement which invoked this stored
function/trigger.
... when trying to perfom this query:
UPDATE `db`.`oc_product` SET `quantity` = '220' WHERE `oc_product`.`product_id` = 50
Trigger for db2, table stock:
DROP TRIGGER IF EXISTS t1_ai &&
CREATE TRIGGER t1_ai BEFORE UPDATE ON stock FOR EACH ROW BEGIN
IF #__disable_trigger_t1t2 = 1 THEN
SET #__disable_trigger_t1t2 = NULL;
ELSE
SET #__disable_trigger_t1t2 = 1;
-- trigger logic goes in here
UPDATE `db1`.oc_product
SET `quantity` = NEW.quantity
WHERE SKU = NEW.SKU;
END IF;
END &&
Trigger for db1, table oc_product:
DROP TRIGGER IF EXISTS t2_ai &&
CREATE TRIGGER t2_ai BEFORE UPDATE ON oc_product FOR EACH ROW BEGIN
IF #__disable_trigger_t1t2 = 1 THEN
SET #__disable_trigger_t1t2 = NULL;
ELSE
SET #__disable_trigger_t1t2 = 1;
-- trigger logic goes in here
UPDATE `db2`.stock
SET `quantity` = NEW.quantity
WHERE SKU = NEW.SKU;
END IF;
END &&
Any idea how to fix that error?
Extra information:
If I perfom this query for the stock table on db2:
UPDATE `db2`.`stock` SET `quantity` = '220' WHERE `stock`.`id` = 7631;
Then the trigger t1_ai do the job, but not vice-versa
Cause: You cannot update/delete/insert to a table (stock) where the trigger is invoked:
Within a stored function or trigger, it is not permitted to modify a
table that is already being used (for reading or writing) by the
statement that invoked the function or trigger.
Doing so will generate Error 1442:
Error Code: 1442
Can't update table 'oc_product' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
What is happening here, UPDATE on stock table fires the first trigger 't1_ai' which in it's SQL attempts to update the oc_product table, which has a trigger 't1_ai' which attempts an update/change back on the stock table.
So, as mentioned above you:
it is not permitted to modify a table that is already being used (for
reading or writing)
For this whole flow (cascading triggers) the stock is still in use (hence locked for further read or write) i.e. the first table update where these cascading triggers got fired.
Suggestion:
Try implementing a procedure and call it via your application.
I am having trouble with a trigger in MySQL. I have a column named "last_modified" that I want to be automatically updated with the current date and time when it is the table is edited. Using a trigger, this is my SQL query:
delimiter //
CREATE TRIGGER trg_update_responders BEFORE UPDATE ON survey_responders
FOR EACH ROW
BEGIN
UPDATE survey_responders
SET NEW.last_modified = CURRENT_DATETIME();
END;//
However, when I update the table, such as with this query:
UPDATE survey_responders SET first_name = "bob" WHERE id = "1";
MySQL Workbench displays error 1442: "Can't update table 'table_name' in stored function/trigger because it is already used by statement which invoked this stored function/trigger"
I have looked at similar questions with the same error but still have not fixed it. Help is appreciated.
** UPDATE **
This did the trick:
delimiter //
CREATE TRIGGER trg_update_responders BEFORE UPDATE ON survey_responders
FOR EACH ROW
BEGIN
SET NEW.last_modified = CURRENT_TIMESTAMP();
END;//
Seems like I simply did not need to repeat the
UPDATE survey_responders
and CURRENT_DATETIME() did not exist, I had to use CURRENT_TIMESTAMP().
This did the trick:
delimiter //
CREATE TRIGGER trg_update_responders BEFORE UPDATE ON survey_responders
FOR EACH ROW
BEGIN
SET NEW.last_modified = CURRENT_TIMESTAMP();
END;//
Seems like I simply did not need to repeat the
UPDATE survey_responders
and CURRENT_DATETIME() did not exist, I had to use CURRENT_TIMESTAMP().
What you are trying to do is not possible using a trigger.
Within a stored function or trigger, it is not permitted to modify a
table that is already being used (for reading or writing) by the
statement that invoked the function or trigger.
Source
You need to do this some other way.
See here: MySQL - Trigger for updating same table after insert
The typical way to do that, is to create a stored procedure, that
inserts into/Updates the target table, then updates the other row(s),
all in a transaction.
I get an error (1064) when attempting to run the following... (MySql 5.5.9)
query:
CREATE TRIGGER clearChat AFTER INSERT ON chat
FOR EACH ROW
BEGIN
DELETE p.* FROM chat p LEFT JOIN (SELECT t.id FROM chat t ORDER BY t.id DESC LIMIT 50) x ON x.id = p.id WHERE x.id IS NULL
END;
the error is:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'END' at line 5
Any assistance would be great.
Last Edit: Updated to show the 'FOR EACH ROW' and 'BEGIN'
You're missing FOR EACH ROW before DELETE: http://dev.mysql.com/doc/refman/5.1/en/create-trigger.html
Edit: There are more issues. The correct syntax is below:
delimiter |
CREATE TRIGGER clearChat AFTER INSERT ON chat
FOR EACH ROW BEGIN
DELETE p.* FROM chat p LEFT JOIN (SELECT t.id FROM chat t ORDER BY t.id DESC LIMIT 50) x ON x.id = p.id WHERE x.id IS NULL;
END;
|
delimiter ;
Edit 2:
I don't think that query is allowed to be in a trigger at all based on this http://dev.mysql.com/doc/refman/5.1/en/faqs-triggers.html#qandaitem-B-5-1-9:
A trigger can access both old and new
data in its own table. A trigger can
also affect other tables, but it is
not permitted to modify a table that
is already being used (for reading or
writing) by the statement that invoked
the function or trigger.
Since you aren't using OLD or NEW, I don't think you can modify chat since the trigger is triggered on inserts to chat.
I had the same problem with the following statement, it ALWAYS gave me a syntax error on even this simplified delete statement (originally was DELETE FROM APP_CACHE_VIEW WHERE APP_UID = OLD.APP_UID;):
CREATE TRIGGER APPLICATION_DELETE BEFORE DELETE ON APPLICATION
FOR EACH ROW
BEGIN
DELETE FROM APP_CACHE_VIEW;
END
If I changed the SQL command to the following then it WORKED but I don't understand why:
DELIMITER $$
CREATE TRIGGER APPLICATION_DELETE BEFORE DELETE ON APPLICATION
FOR EACH ROW
BEGIN
DELETE FROM APP_CACHE_VIEW;
END$$
DELIMITER ;