I have a table: ID,name,count,varchar(255)
Now, what i'd like is to increase the "count" each time that row in the table is updated.
Of course, the easy way is to read first, get the value, increase by 1 in php, then update with the new value. BUT!
is there any quicker way to do it? is there a system in mysql that can do the ++ automatically? like autoincrement, but for a single entity on itself?
I see two options:
1.
Just add this logic to every update query
UPDATE `table` SET
`data` = 'new_data',
`update_counter` = `update_counter` + 1
WHERE `id` = 123
2.
Create a trigger that will do the work automatically:
CREATE TRIGGER trigger_name
AFTER UPDATE
ON `table`
FOR EACH ROW
BEGIN
UPDATE `table`
SET `update_counter` = `update_counter` + 1
WHERE `id` = NEW.id
END
Create a trigger:
http://dev.mysql.com/doc/refman/5.1/en/create-trigger.html
Triggers are pieces of code that are "triggered" by the database on certain events. In your case, the event would be an update. Many RDBMS support triggers, so does MySQL. The advantage of using a trigger is that every piece of your PHP logic that updates this entity, will implicitly invoke the trigger logic, you don't have to remember that anymore, when you want to update your entity from a different piece of PHP logic.
you can look up at the trigger
or can do with the extra mysql query
update table set count=count+1 ;
UPDATE table SET name='new value', count=count+1 WHERE id=...
An SQL update can use fields in the record being updated as a source of data for the update itself.
Related
I have a MySQL database and I need to auto increment a column by 1 every time I do an insert or update. If I had to increment the column only during insert I could have used the built-in autoincrement option (usually used for primary keys). How can I do it for insert and updates?
EDIT
Sorry, I posted the wrong question, what I actually need is to increase a counter by 1 every time I do an insert or update, the current value of the counter has to be stored in the row being created or updated. The counter starts from 1 and never comes back, it just keep increasing "forever" (BIGINT). Think of this counter as a lastupdate timestamp but instead of using real unix timestamps I use an ever increasing integer (monotonic increasing value).
P.S. I'm implementing a syncronization mechanism between many local SQLite databases and one master MySQL database so the behavior has to be implemented on both dbms.
The current state of the counter can be stored on a separate table of course
Simply use triggers.
Something like this:
CREATE TRIGGER trgIU_triggertestTable_UpdateColumnCountWhenColumnB
ON dbo.triggertestTable
AFTER INSERT,UPDATE
AS
BEGIN ...
OR you can do something like this:
INSERT INTO TableA (firstName, lastName, logins) VALUES ('SomeName', 'SomeLastName', 1)
ON DUPLICATE KEY UPDATE count = count + 1;
I see two ways to do what you want.
The first is for inserts, when you should use the autoincrement key. But, when we talk about autoincrement updates, it's a little bit more complicated. For me, the best solution is to do a trigger.
You could use a trigger like this:
CREATE TRIGGER update_trigger
AFTER UPDATE
ON `your_table`
FOR EACH ROW
BEGIN
UPDATE `your_table`
SET `the_field_you_want_autoincrement` = `the_field_you_want_autoincrement` + 1
WHERE `pk` = NEW.pk
END
There's no declarative auto-increment-on-update feature. And the auto-increment must be part of your primary key, so this is probably not your counter.
You can do this with triggers.
CREATE TRIGGER MyTrigger BEFORE INSERT ON MyTable
FOR EACH ROW
SET NEW.counter = 1;
CREATE TRIGGER MyTrigger BEFORE UPDATE ON MyTable
FOR EACH ROW
SET NEW.counter = OLD.counter+1;
These must be BEFORE triggers, because you can't set column values in an AFTER trigger.
Re your comments:
I don't get the "for each row on the second statement"
This is a required clause for all MySQL triggers, because the trigger runs for each row inserted. You can insert multiple rows in a single INSERT statement:
INSERT INTO MyTable VALUES (...), (...), (...), ...
INSERT INTO MyTable SELECT ... FROM ...
The insert trigger will initialize each row inserted.
Re your updated question:
The solution with triggers I show above will actually work for the scenario you describe, where you want a counter column to start at 1 at INSERT time, and increase by 1 every time you update.
The solution with INSERT...ON DUPLICATE KEY UPDATE does not work, because it won't increment the counter if a user simply does an UPDATE statement. Also the user is required to include the initial counter value 1 in their INSERT statement.
The insert trigger sets the initial value to 1 even if a user tries to give a different value in their INSERT statement. And the update trigger will increment the counter even if the user uses INSERT...ON DUPLICATE KEY UPDATE or UPDATE.
But don't use a REPLACE statement, because this would do a DELETE followed by a new INSERT, and thus it would run the insert trigger, and reset the counter to 1.
Having a table with the name transitions, I want to change the values of all the rows after any update is made.
I'm using the following trigger, which changes only the ROW that I'm making the update to.
CREATE TRIGGER signaturetrigger BEFORE UPDATE ON `transactions` FOR EACH ROW
BEGIN
SET New.signature = '288';
END
I'm trying to change all the rows to signature = 288, how can I modify the trigger in order to archieve that? I thought that using FOR EACH ROW would be enough.
Thanks in advance.
You can use an after update trigger with an update statement:
CREATE TRIGGER signaturetrigger AFTER UPDATE ON `transactions`
FOR EACH ROW
BEGIN
UPDATE transactions
SET New.signature = '288';
END;
This does seem like a very strange thing to do, however.
Consider an alternative: just add an UpdatedAt column into the table and update the signature in that row. Then, when you want the most recent signature use:
select signature
from transactions
order by UpdatedAt desc
limit 1;
An index on transactions(UpdatedAt, signature) will make this quite speedy. And, the update will go much, much faster than updating all rows.
I have a mysql Innodb table 'classrooms_subjects' as
id|classroom_id|subject_id
classroom_id & subject_id are composite keys. Whenever i insert a row with classroom_id & subject_id, my id field is inserted as 0.
Now i want to create a trigger which will enter id field as last_inserted_id()+1.
Also I need to take care of multiple records inserted at a time. My trigger is like below:
CREATE TRIGGER `increment_id` AFTER INSERT ON `classrooms_subjects`
FOR EACH ROW BEGIN
UPDATE classrooms_subjects
SET classrooms_subjects.id = LAST_INSERT_ID() + 1 WHERE id=0;
END
when i am inserting a record I am getting the error as:
"Cant update table in trigger because it is already used by statement which invoked this trigger
For general info: using an update statement inside the trigger isn't right.
Better to use a before insert trigger and simply assign the value of your column using NEW.id
http://dev.mysql.com/doc/refman/5.7/en/trigger-syntax.html
A column named with OLD is read only. You can refer to it (if you have
the SELECT privilege), but not modify it. You can refer to a column
named with NEW if you have the SELECT privilege for it. In a BEFORE
trigger, you can also change its value with SET NEW.col_name = value
if you have the UPDATE privilege for it. This means you can use a
trigger to modify the values to be inserted into a new row or used to
update a row. (Such a SET statement has no effect in an AFTER
trigger because the row change will have already occurred.)
You should probably structure your table to make the auto_increment work properly. Better a solution that works when multiple sessions are inserting to the DB at once.
I'm fairly new to triggers and have already tried searching for a solution to my question with little results. I want to update a single row's start time column whenever it's active column is set to 1.
I have two columns ACTIVE (number) and START_TIME (timestamp) in my_table. I would like to create a PL/SQL trigger that updates the START_TIME column to current_timestamp whenever an update statement has been applied to the ACTIVE column - setting it to 1.
So far I have only seen examples for inserting new rows or updating entire tables which isn't what I'm looking to do. I'd have thought there would be a fairly simple solution to my problem.
This is what I've got so far from other examples. I know the structure of my solution is poor and I'm asking for any input to modify my trigger to achieve my desired result.
CREATE OR REPLACE TRIGGER routine_active
AFTER UPDATE ON my_table
FOR EACH ROW
WHEN (my_table.ACTIVE = 1)
begin
insert my_table.start_time = current_timestamp;
end;
\
you can use like this .it may help you
write the update query instead of insert query
CREATE OR REPLACE TRIGGER routine_active
AFTER UPDATE ON my_table
FOR EACH ROW
WHEN (new.ACTIVE = 1)
begin
update my_table set start_time =current_timestamp;
end;
I think it should be a BEFORE UPDATE, not AFTER UPDATE, so it saves both changes with a single action. Then you don't need the INSERT or UPDATE statements. I also added the "OF active" clause, so it will only start this trigger if that column was updated, which may reduce the workload if other columns get updated.
CREATE OR REPLACE TRIGGER routine_active
BEFORE UPDATE OF active ON my_table
FOR EACH ROW
BEGIN
IF active = 1
THEN
:NEW.start_time = current_timestamp;
END IF;
END;
I am wondering if it is possible to perform a SQL query then update another table with the generated ID and continue through all of the rows?
I have this SQL query that works but what I need to do is after each row is added to cards to then update merged.cars_id with the last generated ID so they are linked. normally I would do this with PHP but ideally I would like to just do it with MySQL if possible.
MAIN QUERY
INSERT INTO cards (first_contact_date, card_type, property_id, user_id)
SELECT first_contact_date, 'P', property_id, user_id FROM merged
THEN I NEED WITH MATCHING ROWS (Roughly)
UPDATE merged SET merged.card_id = LAST_INSERT_ID (FROM ABOVE) into the matching record..
Is something like this possible and how do I do it?
I would recommend using MySQL triggers to do this
http://dev.mysql.com/doc/refman/5.0/en/create-trigger.html
A trigger is a function that will be executed AFTER or BEFORE the INSERT or DELETE or UPDATE is done over any record of your table.
In your case you need to do a AFTER INSERT on cards that just updates the merged table. Make sure its AFTER insert as you wont be able to access the new row's ID otherwise.
The code would look something like this, assuming the id field from the cards table its named "id"
delimiter |
CREATE TRIGGER updating_merged AFTER INSERT ON cards
FOR EACH ROW BEGIN
UPDATE merged SET card_id = NEW.id;
END;
|
delimiter ;
May I suggest Stored Procedures?
http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html
--EDIT--
Ah yes, triggers. For this particular situation, Jimmy has the answer. I will leave this post for the sake of the link.
I would set up a trigger to do this. For mysql, read http://dev.mysql.com/doc/refman/5.0/en/triggers.html. This is what triggers are designed to handle.