I cannot seem to track down why MySQL is throwing an error when trying to update a column in a table given the following.
The update query is:
update jobitems set itemprice=itemprice/100;
The error is:
Error Code: 1054. Unknown column 'JobID' in 'where clause'
When I remove the following from the triggers on jobitems, the update works.
DELIMITER $$
CREATE
DEFINER=`root`#`localhost`
TRIGGER `alacarte`.`jobitems_beforeupdate`
BEFORE UPDATE ON `alacarte`.`jobitems`
FOR EACH ROW
Begin
declare customer varchar(45);
Set #customer = (select CustomerID FROM jobs WHERE JobID=old.JobID);
If new.ItemCompleted<=>1
AND (select InvoiceStatus
FROM
(Select InvoiceStatus, CustomerID
FROM invoices
as custinvoices
Where CustomerID=#customer)
as InvoiceStatus
WHERE InvoiceStatus='Open') IS NULL
then
insert into invoices
set
CustomerID=#customer,
InvoiceBillToName=ifnull((select CustomerName FROM customers WHERE CustomerID=#customer),'-'),
InvoiceBillToAddress=etc;
Naturally, the jobs table has a JobID and CustomerID column. Many other triggers and our front end utilize these columns and they work flawlessly.
The following query works and returns "cust-000002" which is correct.
Set #customer = (select CustomerID FROM jobs WHERE JobID='ALC-20121119-001');
select #customer;
Also the following query works (ItemCompleted=0 for this jobitem, so it is not triggering the above trigger):
update jobitems set itemprice=itemprice/100 where JobID='ALC-20121119-001';
So, I am officially stuck with the above info. Please help :).
Update:
Eliminating the variable and replacing "#customer" with (select CustomerID FROM jobs WHERE JobID=old.JobID) throughout the trigger give the same error, as was expected.
Also, by modifying the trigger, the error goes away. I used the variable in simply a new way and it works. The following adds the output of #customer to each job into a test column and works perfectly. Err!
declare customer varchar(45);
Set #customer = (select CustomerID FROM jobs WHERE JobID=old.JobID);
If new.ItemCompleted<=>1
then
update jobs set testcol=#customer where JobID=old.JobID;
end if;
Update:
Just to make sure I am not crazy, I copy and pasted the trigger back and I get the exact same error message as before so this problem is reproducable. Also, just to be thorough, entries with "ItemCompleted=1" cannot be updated without error and entries with "ItemCompleted=0" can be updated without error found from trying to edit entries via our front end one by one. I figured I'd just make sure because I am thouroughly confused right now.
I would try qualifying JobID by calling it jobs.JobID wherever it is used, for additional disambuguation.
But I my dba instinct suggests that the actual problem may be somewhere else -- you may have another trigger that's getting fired off by something that's happening in this trigger... perhaps a trigger on the jobs or invoices tables? Or in an AFTER UPDATE on this same table?
Turn on your general log with SET GLOBAL general_log = 1 and then run the query that causes the error in the trigger.
Then turn off the general log again (so the error is easier to find, and so don't fill your hard drive), and go look in the general log at exactly what was really happening when you hit the error... the general log should actually log the queries that get run from inside the triggers, in addition to the queries you manually ran that initially caused the triggers to fire.
When you do:
(select CustomerID FROM jobs WHERE JobID=old.JobID)
JobID, without a prefix, is the column from the jobs table, which you say you have. Now old.JobId is jobitems.JobID, since old references the table used in the update that triggers this.
Check that the column name you are matching from jobitems is exactly jobID.
Related
Am populating a table using a trigger after an insert event occurs on another table and that worked fine. However i then noticed that the trigger would still insert a new row for existing records. To fix this, I want to create the trigger again but this time it would only fire if a condition is met...but not having previously used triggers in the past am getting a syntax error and not able to identify what am doing wrong. Kindly have a look and help me fix this
CREATE TRIGGER `students_gen_insert`
AFTER INSERT ON `students` FOR EACH ROW
BEGIN
INSERT INTO records (student_id, subject_id)
SELECT new.student_id, subjects.subject_id
FROM subjects
WHERE category = new.class;
END;
Am currently using MySql 5.6.17 version.
It is generally not a good idea to SELECT from the table the trigger is on, and forbidden to UPDATE or INSERT (not that you are doing those). Assuming you are trying to get the values for the row just inserted, the first SET ... SELECT you have is needless; just use NEW.fieldname to get the fields of the inserted row.
The second SET ... SELECT and following condition are a bit confusing. If referential integrity is being maintained, I would think it would be impossible for the records table to refer to that particular student_id of the students table at the point the trigger is executed. Perhaps this was to avoid the duplicate inserts from the trigger's previous code? If so, it might help for you to post that so we can pinpoint the actual source of redundant inserts.
I am working on a project, and I had to make a few changes to a table in order to help speed I am working on a project, and I had to make a few changes to a table in order to help speed things up. I tried to create the following trigger, but it does not work and just gives me the standard #1064 you have an error in your syntax error.
create trigger _wc_insert_trigger before insert on widget_components
set new.component_id = (select id from components c where c.part_no=new.part_no)
I've never worked with triggers before, and I don't really understand everything that I get from Google responses.things up. I tried to create the following trigger, but it does not work and just gives me the standard #1064 you have an error in your syntax error.
Any ideas on how to get something like this to work? I don't have the budget to go in and refactor the existing application to take into account this change.
delimiter |
create trigger wc_insert_trigger before insert on widget_components
FOR EACH ROW BEGIN
set new.component_id = (select id
from components c
where c.part_no=new.part_no);
END
|
delimiter ;
I created a simple UPDATE AFTER INSERT trigger to sum two DECIMAL(10,2) fields and update a 3rd DECIMAL(10,2) field with the summed value.
The trigger code is:
delimiter |
CREATE TRIGGER calc_ttl_cost AFTER INSERT ON buybox_rec
FOR EACH ROW
BEGIN
UPDATE buybox_rec SET total_cost = (price+shipping_cost);
END;
|
I'm using phpMyAdmin to run the SQL commands, so I know that the trigger is being created successfully. Furthermore, if I run the UPDATE buybox_rec SET total_cost = (price+shipping_cost); SQL statement alone, it works as expected. (I've also tried the same code with back-ticks around the field names, but I wouldn't be writing all this if that worked)
The problem is that when I insert a new row, the trigger doesn't work and this error is thrown:
#1442 - Can't update table 'buybox_rec' in stored function/trigger
because it is already used by statement which invoked this stored
unction/trigger.
The error seems like some sort of recursive or circular reference problem, but I can't figure out where/what the problem is.
I also tried creating a stored procedure and calling it from within the trigger to try obtaining the same result, but I got the same error.
I checked a bunch of other SO questions related to MySQL UPDATE triggers and did some Googling, but here I am.
Is this out of the scope of MySQL? It seems like such a common and easy task to allow for.
Does anyone know how I accomplish this task autonomously? (AKA I don't want to hear about summing the fields after the fact via PHP, for example)
THanks for any help
The problem is that you're trying to modify the contents of a table which is already being used by the UPDATE + TRIGGER operation. This simply can't be done, but you have alternatives.
For example, if your meaningful data (or independent variables) are price and shipping cost while the total cost depends on them, you could keep only the first two in your table, and maybe have a very simple VIEW (something like SELECT price, shipping_cost, price+shipping_cost total_cost FROM buybox_rec, or whichever other fields you need) if you want to keep an eye at the total.
I'm trying to create a database with history in mind (experience shows you'll have to do this one day or another).
I've asked here database-design-how-to-handle-the-archive-problem but there's no better anser than the link here.
My problem is about where to do the code and technically, how (MySQL gives me headaches). First I've started doing this in Php: before doing any insert, duplicate the record mark it as "obsolete" then modify the record.
But there's a dependency problem (manytomany and manytoone associations must be updated as well) which implies coding (one way or another) all the dependancies and updates that come with the tables (which is not acceptable).
So I'm thinking about doing all the work on the database server side. This would greatly simplify my Php code.
The problem is that I have to "archive" the current record before modifying it. To do so, the code must be in a trigger "before update".
Here's my code:
DELIMITER ;;
DROP TRIGGER IF EXISTS produit_trigger_update_before;
CREATE TRIGGER produit_trigger_update_before
BEFORE UPDATE ON produit
FOR EACH ROW BEGIN
/* */
INSERT INTO produit SET
id_origine = OLD.id_origine,
date_v_creation = OLD.date_v_creation,
date_v_start = OLD.date_v_debut,
date_v_end = NOW(),
...
last_record = OLD.last_record;
/* Dependancies : */
SET #last=LAST_INSERT_ID();
UPDATE categorie_produit SET id_produit=#last
WHERE id_produit = OLD.id;
UPDATE produit_attribut SET id_produit=#last
WHERE id_produit = OLD.id;
END;;
DELIMITER ;;
If I get this code working, all my problems are gone. But damn it, it's not working:
mysql> update produit set importance=3;
ERROR 1442 (HY000): Can't update table 'produit' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
mysql> Bye
In this page there's a working sample, which uses INSTEAD OF UPDATE clause in the trigger. MySQL doesn't seem to support this.
So my question is both conceptual (= have you any other "principle" that could work) and/or technical (= can you make this trigger work).
If I get this code working, all my problems are gone. But damn it, it's not working:
As a rule you can't have a trigger on table A trigger inserts into table A - since that could cause an endless loop. (Trigger mutation in Oracle terms)
Personally I would not do this using triggers. Triggers can do "audit logging" - but this is not what you want here.
I suggest you solve it programatically - either with a PHP function or a MySQL stored procedure (whatever your preference) that you call something like "ModifyProduit".
The code would then do basically what you have the trigger above do. (It might be easier to just have the code set date_v_end on the current row, and then insert a completly new row. That way you don't have to mess around with updating your referenced tables)
you can do history of a table with an auxiliary table like this (i've done this for many tables on mysql and the speed is very good):
table produit_history has the same structure as produit + 2 additional columns: "history_start DATETIME NOT NULL" and "history_stop DATETIME DEFAULT NULL".
there are 3 triggers on produit table:
AFTER INSERT: in this trigger there is a simple insert into produit_history of the same data with history_start = NOW() and history_stop = NULL (NULL means the current row is valid)
AFTER UPDATE: this trigger performs two queries. The first is un update like this:
UPDATE produit_history set history_stop = NOW() WHERE id_origine = OLD.id_origine AND history_stop IS NULL;
The second query is an insert identical to the one in the AFTER INSERT trigger.
AFTER DELETE: this triggers there is a simple update which is identical to the one in the AFTER UPDATE.
You can then query this history table and obtain snapshots at whatever time you're interested in with the following where condition:
WHERE (history_start <= "interesting_time" AND (history_stop IS NULL OR history_stop > "interesting_time"))
Is it possible to check whether a particular value in a column exists in other databases using trigger? These two databases are located inside the same MYSQL instance. Specifically, what I want to do is this:
Before a row is added to a table ( Document_Index_table) inside Database A ( Document_DB).
A trigger is fired. This trigger carries the one of the column value (usr_id) inside the row and pass it to Database B ( User_Control_DB).
Based on the values, User_Control_DB will check whether the usr_id exists in column usr_id of the table (Usr_Information).
If exists, then return a true to Document_DB and the row in 1. is allowed to add to the Document_DB.
If not, then an error is issued. No row is added to Document_DB.
How can this be done, if it can be done at all?
Edit: Both databases are MySQL databases
So, I'm a complete novice at database development, but you could do something like this:
Create a 'Before' insert trigger on your document_index_table.
The trigger does something like this:
declare numRows integer;
select count(*) from user_control_db.usr_information where usr_id = NEW.usr_id into num_rows;
if (numRows > 0) then
call NonExistentProc();
end if;
I believe that this would accomplish what you wanted. It'll produce an error like "PROCEDURE documentdb.NonExistenProc does not exist" and skip the insert if there isn't at least one row that has the matching usr id in the user control db.
Again, I'm a novice at this DB stuff so there might be a more elegant way, but this worked for my single test case.
Hope that helps.