MySql cannot update a DATETIME field - no record found - mysql

I have a table in MySql 5.6.10 defined as this:
When I do a select query (from HeidiSQL client) for a particular record filtering on the id_failed_delivery_log column, the record is found successfully, but when I use the same filter for the UPDATE command, then no record is found and no error reported:
When I update a different column using the same filter, the update works and I can see the updated value. Then there is an issue with an update to this particular column.
I've also tried updating with a time function instead of hard-coded date value, for example with the now() function but I still get the same result and the record is not found.
Could it be caused by the 'Default' value is set to CURRENT_TIMESTAMP?

After further investigation I found the reason why I couldn't update that field. I was not totally familiarized with the database definition and I found that there was a trigger in the same schema that forced to keep the date_created column with the same value:
SET #OLDTMP_SQL_MODE=##SQL_MODE, SQL_MODE='STRICT_ALL_TABLES';
DELIMITER //
CREATE TRIGGER `failed_delivery_log_before_update` BEFORE UPDATE ON
`failed_delivery_log` FOR EACH ROW BEGIN
SET NEW.date_created = OLD.date_created ;
END//
DELIMITER ;
SET SQL_MODE=#OLDTMP_SQL_MODE;
I removed this trigger temporarily in order to test. Once removed, the updated worked fine. The trigger execution was not reported in the SQL client, so it was difficult to find out its execution.

Related

How to set a MySQL Trigger the correct way

i have a database table that gets updated via a CMS. Sometimes, there is one field that gets updated and then another field should get updated as well. I tried to get this done by just modifying the php code of the CMS, where the value gets saved in the DB. The problem is, with every update of the CMS this is gone.
I came across MySQL Triggers and i think this is a good way to do this. So whenever this field is updated, it should also update the other field with a value that will always be the same. But i cant quite get my head around the syntax, to get this going...
I tried:
CREATE TRIGGER after_unique_content_update
AFTER UPDATE
ON articles FOR EACH ROW
BEGIN
IF OLD.date <> new.date THEN
INSERT INTO release=2020
END IF;
END
But it is not working. So what i try to do: Every time in the CMS someone changes the date, the release for that db entry should be set to 2020. The standard for release is NULL. With the above trigger, nothing happens after the date is changed... Never worked with Trigger or Events in MySQL before...
How can i set the release to 2020 when the date field for that entry is updated?
Thanks for your help in advance!
best regards
CREATE TRIGGER before_unique_content_update
BEFORE UPDATE
ON articles
FOR EACH ROW
SET NEW.release = CASE WHEN OLD.date <> NEW.date
THEN 2020
ELSE NEW.release
END;
Firstly the condition is checked by the trigger, and, if the condition matched, new value to the column is set to 2020 (or, maybe, it's better to set it not to 2020 but to YEAR(CURRENT_DATE)?). If the condition not matched then the value is not altered (assigned value is the same as current one).
After the trigger performs this task, actual table data update is performed.
AFTER UPDATE trigger is not applicable - when it fires the data in the table is already set to the value specified in a query.

Trigger Syntax mySQL

I want to make the Total column receive the total sum between the other columns, but i keeping getting the error 1193.
I'm new to mySql so i dont know where i should start looking to solve the error.
DELIMITER $$
CREATE TRIGGER Total
BEFORE INSERT ON `despesas` FOR EACH ROW
BEGIN
SET Total = Abertura_Processo+Telefone+Correspondencia+Cartorio+Conservatorio+Servico_Financas+Taxas_Emolumentos+Honorarios;
END;
$$
DELIMITER ;
I've read a bit and for what i've understood I need to create a variable, but i dont know how.
The total column has its values manually inserted i want it to be automatically
You can reference the newly inserted record's field via NEW.column_name in the before insert trigger. By setting a value to such a column, you can change the value being inserted. So, change the value setting line as follows:
SET NEW.Total = NEW.Abertura_Processo+NEW.Telefone+NEW.Correspondencia+NEW.Cartorio+NEW.Conservatorio+NEW.Servico_Financas+NEW.Taxas_Emolumentos+NEW.Honorarios;
Note, you may use generated columns as an alternative to this trigger.
Got it, every thing worked fine.

MySQL throws a warning when executing a "before delete" trigger

I have a small database (SQLfiddle) that I am designing. I am trying to create a trigger so that when a row is deleted from downtime, a matching history line gets added to downtimeHistory:
CREATE TRIGGER `announce`.`downtime_BEFORE_DELETE` BEFORE DELETE ON `downtime` FOR EACH ROW
BEGIN
INSERT INTO downtimeHistory (serviceName, startTime) VALUES(OLD.serviceName, OLD.startTime);
END
However, MySQL doesn't care for this trigger. It allows me to create it, and it appears to be functioning correctly, but it throws an error each time the trigger is executed:
1 row(s) affected, 1 warning(s): 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it invokes a trigger or a stored function that inserts into an AUTO_INCREMENT column. Inserted values cannot be logged correctly.
This would make sense to me if I were trying to do something with the id or endTime columns, but updating startTime shouldn't matter since it just provides a default value.
So...why is it throwing this error? How do I stop it? Should I just ignore it?
Your trigger inserts into the downtimeHistory table. The id column is AUTO_INCREMENT.
The error message tells you that this combination is not allowed.
The INSERT INTO.... statement implicitly causes the ID value to be set.

Syntax exception on trigger with multiple statements with MySQL and JDBC

I am trying to create a trigger that performs multiple operations in MySQL 5.5.28 with InnoDB.
I have two tables, "test" and "test_watcher": changes to the first are recorded in the watcher table with the help of triggers. The last trigger needs to perform 2 operations on DELETE, it works in MySQL Workbench (with DELIMITER) but doesn't if I create it with JDBC.
CREATE TRIGGER `AD_test_FER` AFTER DELETE
ON `test`
FOR EACH ROW
BEGIN
-- if it's been inserted, modified and deleted but never synced,
-- the revision is NULL: no one needs to know about it
DELETE FROM test_watcher WHERE pk = OLD.id AND revision IS NULL;
-- if it has been synced already, we just update the flag
UPDATE test_watcher SET flag = -1 WHERE pk = OLD.id;
END;
I keep getting com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax.
I know it works with DELIMITER $$ in Workbench, but JDBC doesn't support it.
I've achieved it in PostgreSQL and would post the code if necessary.
This behavior might be caused by the connection property allowMultiQueries=true. My guess is this property will make MySQL break up queries on the ; as a query separator and then execute those as separate queries, essentially breaking your trigger creation code.
As you said in a - now deleted - answer that adding allowMultiQueries=true actually solved the problem (contrary to my expectiation), the problem might actually be the last ; in your query. So another thing to check is if the problem goes away by removing the last ; (in END;) in your script (and not using allowMultiQueries=true). Some database don't consider ; to be valid at the end of a statement (as it is actually a delimiter to separate statements).
(this answer is based on my comment above)
If JDBC does not support delimiters (DELIMITER is a client command), then execute these two statements separately - one by one.

MySQL: trigger with clause "instead of update"

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 &lt= "interesting_time" AND (history_stop IS NULL OR history_stop &gt "interesting_time"))