I am dealing with a legacy application that is using MariaDB to emulate a queue. One of the key things missing is that the original design doesn't insert the time the messages in the queue were inserted meaning that the order the messages are processed is not guaranteed.
So far the messages appear to be processed in order as we're only using a single MariaDB instance but I would like to add a created_on column to ensure this continues.
My question is that I need to backfill the created_on column and i was wondering if MariaDB stored the time a given row was inserted into the database?
I realise that unless it is in the schema it is unlikely but occasionally databases will have non-standard extensions that capture this sort of thing. Oracle for example has similar functionality to this.
MariaDB does not have a hidden timestamp. If the table has an AUTO_INCREMENT, that might suffice since you are asking for order, not specifically time.
My opinion of queuing via MySQL/MariaDB: "Don't queue it, just do it". The effort of queuing and dequeuing can become a burden, especially in end cases.
Yes you can, if you were to create a field make sure when you create the field you have the following:
create table test_created_on_table(
created_on timestamp default now() on update now()
);
If you already have a field just take off the "CURRENT_TIMESTAMP" flag on the created field. Whenever you create a new record in the table, just use "NOW()" for a value.
Or.
On the contrary, remove the 'ON UPDATE CURRENT_TIMESTAMP' flag and send the NOW() for that field. That way actually makes more sense.
This would track when row is inserted or updated.
There's another way of doing it by db trigger:
Adding a ModifiedTime
Adding a modified timestamp to a table is the most straight forward. All your have to do is create the field of type TIMESTAMP, and by default, MySQL will automatically update the field when the row is modified.
There are a couple of things to be aware of:
While you can have multiple TIMESTAMP fields in a row, only one of
these can be automatically updated with the current time on update.
If your UPDATE query contains a value for your ModifiedTime field,
this value will be used.
So, to add your modified timestamp field to an existing table, all you need is:
ALTER TABLE my_table ADD ModifiedTime TIMESTAMP;
Adding a CreatedTime
Adding a CreateTime value is a little more involved.
On the latest versions of MySQL it is apparently possible to create a DateTime field with a default value of CURRENT_TIMESTAMP. This wasn’t an option for me as I was having to support a somewhat older version, besides, even on the newer versions of MySQL it is not possible to have more than one field using CURRENT_TIMESTAMP, which of course we are in order to get ModifiedTime working.
So, in order to get a created timestamp, firstly we must add a DATETIME field to the table.
ALTER TABLE my_table ADD CreatedTime datetime NOT NULL;
Note, that this must be created as NOT NULL in order for the next part to work (this is because setting NOT NULL forces an automatic all zeros default).
Next, we must create a trigger, which will automatically be fired when we insert a value into our table and set the created timestamp.
DELIMITER //
DROP TRIGGER IF EXISTS my_table_insert_trigger//
CREATE TRIGGER my_table_insert_trigger
BEFORE INSERT ON my_table
FOR EACH ROW
BEGIN
IF NEW.CreatedTime = '0000-00-00 00:00:00' THEN
SET NEW.CreatedTime = NOW();
END IF;
END;//
DELIMITER ;
Now, when you insert a value into the table, this trigger will fire and, if you’ve not provided a CreatedTime field in your insert query, it will be set to the current time stamp.
Related
While searching for something else, I found this trigger in our test database:
begin
set NEW.UpdatedAt = now();
end
I'm puzzled... Is this any different from changing the column definition to the following?
alter table TableName change UpdatedAt ON UPDATE CURRENT_TIMESTAMP;
Are any advantages that I'm not seing to doing it in a trigger?
For earlier versions of MySQL, the ON UPDATE was available only for columns of datatype TIMESTAMP. That functionality was not supported for DATETIME or any other datatypes.
And with TIMESTAMP columns, it could be kind of tricky to get table defined with two TIMESTAMP columns to be automatically set; to get NOW() assigned to one column when the row was inserted, and to get NOW() assigned to a different column when the row was updated.
Triggers can work around those limitations.
MySQL Database will be being modified using a PHP Crud system, and I need to track when each record was modified.
For example, if my table has 30 rows, and 30 columns, and I want to put a "Last Modified" beside each individual entry, can I somehow set up 30 TIMESTAMP columns related to each existing column to achieve that?
Or is there a better way?
Here's what I basically want:
Column 1 C1s TIMESTAMP Column 2 C2s TIMESTAMP Column 3 C3s TIMESTAMP...
Red (lastModified) Green (lastModified) Blue (lastModified)
Orange (lastModified) Purple (lastModified) Pink (lastModified)
Yellow (lastModified) Black (lastModified) Brown (lastModified)
... etc
It should be possible to determine which column changed though. As you have access to the OLD and NEW values, you could check for every field if it changed and if it changed enter a new timestamp into the according field. Something like:
CREATE TRIGGER updateTable
BEFORE UPDATE ON tableA
FOR EACH ROW
BEGIN
IF OLD.field1 != NEW.field1 THEN
SET NEW.timestamp1 = now()
END IF;
IF OLD.field2 != NEW.field2 THEN
SET NEW.timestamp2 = now()
END IF;
END
I think that might work, but I haven't tested it.
Not with the native MySQL auto initializing TIMESTAMP/ DATETIME functionality alone.
As of Mysql 5.6.5 you can have as many auto intitializing TIMESTAMP (or DATETIME) columns as you want, however these work at the level of the record, not column.
What I mean by this is you can auto set any TIMESTAMP on creation to the CURRENT_TIMESTAMP. You can also set the TIMESTAMP column to update on modification of the RECORD. However, all columns set to update timestamps on modifcation will update when any column is updated (http://dev.mysql.com/doc/refman/5.6/en/timestamp-initialization.html)
Given this, it only makes sense to have at most 2 auto TIMESTAMP columns: one for recording the creation date, the other for the modification date.
Here's how you create auto incrementing timestamp columns:
ALTER TABLE sometable
ADD COLUMN created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
ADD COLUMN modified_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP;
There is no way with just the auto timestamp functionality to only update when a specific column is modified.
You'd need to implement a trigger with a custom procedure to accomplish your need.
Another way to do what you want as a subset of a greater facility would be to implement a change log. Place a trigger on every table. In each trigger, write an "audit entry" record into a table which has details determined by the trigger logic: which field changed, the old value, the new value, and the timestamp when it occurred.
The audit entry could have an autofilled timestamp instead of explicitly managing it. With a little bit of cleverness, the triggers could feed a common stored procedure which accepts a tablename parameter as well as the other information.
This would provide a complete history of all changes, not just the last one.
I'd like to record the last user and last time a particular row was either inserted or updated in a MySQL table. What is the best way to go about this? Is there some MySQL metadata I can investigate or do I need to create username and timestamp columns myself and then create triggers to populate them?
You need to create separate columns yourself for timestamp and user name. For timestamps there is no need to use triggers to update its value, just declare the timestamp field to use current timestamp as initial value and update value:
CREATE TABLE t1 (
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
The user is bit more interesting. If you are talking about mysql level user, then yes, use triggers or stored procedure using the USER() function. If you are talking about application level users, then I would supply that username as part of the update statement.
UPDATE table SET username='xxx', ... WHERE ...
You can use a column and set it default system date for insert
For update you must use trigger or etcs.
At least in MySQL 5.5.46, you can track tables. This includes structure and data. There, the DB username and timestamp is recorded.
After inserting new data into a table, I need to select some of the new data straight after, so I can use it for inserting into another table.
The only way I can think of doing this is using the 'datetime' field I have in my row, but how would I retrieve the latest date/time inserted.
INSERT statement with NOW() value for datetime
society_select = SELECT socID, creator, datetime FROM societies.society WHERE datetime='[..datetime is the newest...]';
Hope that makes sense. Thank you
There are a number of ways to do this.
Why not make use of a trigger for this?
When a trigger creates a record you can get the id's of the records inserted. You can then do a select and insert new values into the relevant table.
MYSQL has loads of resources on using triggers.
http://dev.mysql.com/doc/refman/5.0/en/triggers.html
Or you can get the number of rows affected then use this to get the required result set in a select statement.
Get the last inserted ID?
If you are inserting one row into the database at a time then you would be able to get the last inserted id from MYSQL. This will be the Primary Key value of the record you last inserted into the database.
You would basically do something like this in mysql:
SET #inserted_id = LAST_INSERT_ID();
Or in PHP you can use the function:
mysql_insert_id(&mysql);
http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html
Sort the results by their datetime in descending order, and select the first of them.
society_select = SELECT socID, creator, datetime FROM societies.society ORDER BY datetime DESC LIMIT 1;
you can use this with an auto increment filed. after inserting data you can retrieve the list inserted id from the table. and use that id to get the latest record.
A trigger as suggested is an option. If you don't want to use that for some kind of reason you can:
Add an integer primary key with auto_increment as ID and sort it DESC (e.g. INT(11))
Sort descending on a timestamp column (ofcourse with an index on it)
Use a trigger after inserting the data. This is for sure the cleaner way.
Another option is to use a method like mysql_insert_id. Assumed that you use PHP. There are of course equivalent methods in other languages as well.
Sorting is not an option(if not wrapped smart in transaction) - If you have multiple writes and reads on the table this might end up pretty ugly.
I was using phpmyadmin to insert some dummy data into a table, and noticed it structured the insert like this:
INSERT INTO `arc`.`transactions` (
`txn_id` ,
`date_time` )
VALUES (
'50005',
CURRENT_TIMESTAMP );
Normally, I'd just not include the field "date_time" and the value is created by mySQL (as the field is of type timestamp), and auto-updates whenever you insert or update a record.
Is there any reason to structure the query as you see it above, explicitly inserting CURRENT_TIMESTAMP? Or is this a phpmyadmin oddity?
It could also be a matter of compatibility. CURRENT_TIMESTAMP is defined by the SQL standard. Automatically updated timestamp columns are not. An app that wants to be portable and record timestamps is better off explicitly specifying the currrent timestamp. And what better way to do that than to use the standard, built-in CURRENT_TIMESTAMP function?
You can have TIMESTAMP fields that don't auto-update (see the TIMESTAMP properties page for how to specify these), so depending on how you define the column, it might not be the case that an UPDATE query automatically adjusts the TIMESTAMP field.
PHPMyAdmin is probably taking the safe approach here and specifying the value to ensure it's updated, no matter the column definition. PHPMyAdmin can probably detect the default value if it wants to, so another possible explanation would be compatibility between various server versions and modes for any SQL that it generates.
It depends solely on date_time column definition. if it is like
`date_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Then you surely don't need to specify anything when inserting or updating a row, but if it is:
`date_time` TIMESTAMP NOT NULL
Then you have to specify something every time you create or update a row