mysql column for insert and different one for update - php

I'm trying to make a table that has two timestamps columns, one will be for when a row is created and the other for when the row is updated. Here's what I tried so far:
CREATE TABLE `tmp` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`data` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created` timestamp NOT NULL ,
`modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
But I'm getting this error:
Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause

You can do this in MySQL 5.6 (available at the time of writing as release candidate but not yet production-ready).
As of MySQL 5.6.5, TIMESTAMP and DATETIME columns can be automatically initializated and updated to the current date and time (that is, the current timestamp). Before 5.6.5, this is true only for TIMESTAMP, and for at most one TIMESTAMP column per table.... For any TIMESTAMP or DATETIME column in a table, you can assign the current timestamp as the default value, the auto-update value, or both
taken from https://dev.mysql.com/doc/refman/5.6/en/timestamp-initialization.html

This is a MYSQL constraint, You can have only one column whose default value will be the systime.
This question can also be referred
How to add "ON update current timestamp" to existing table column

You could write a trigger to add the created timestamp on inserts seperately
delimiter |
CREATE TRIGGER add_created_ts BEFORE INSERT on `tmp`
FOR EACH ROW
BEGIN
SET NEW.created = current_timestamp;
END
|
delimiter ;

Related

MySQL auto add date and time fields on insertion of a new field

My Database DDL is below
CREATE TABLE `user` (
`token` text NOT NULL,
`country` text NOT NULL,
`timezone` text NOT NULL,
`date_registered` date NOT NULL,
`time_registered` timestamp NOT NULL ON UPDATE CURRENT_TIMESTAMP
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
How can I make it so that whenever a new record is created that the date and time will automatically be generated and inserted without relying on PHP to add an extra variable for me to process?
http://example.com/webapps/api/add_token.php?token=%#&country=%#&timezone=%#
The #% are variables generated at run time from my iOS application.
Before a row was generating when I ran my application. But I added two new fields (date_registered and time_registered) and now it is not adding data to the table

timestamp autoupdate not working with ON DUPLICATE KEY UPDATE (PDO)

I've a table folio with timestamp set to auto update.
CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
PDO statement in PHP is not causing the timestamp to update.
$statement = $this->connection->prepare("
INSERT INTO folio(publication, productId)
VALUES(:publication, :productId)
ON DUPLICATE KEY UPDATE
id=LAST_INSERT_ID(id), publication=:publication, productId=:productId");
following manual approach works but is not desirable.
$statement = $this->connection->prepare(
"INSERT INTO folio(publication, productId)
VALUES(:publication, :productId)
ON DUPLICATE KEY UPDATE
id=LAST_INSERT_ID(id), publication=:publication, productId=:productId, timestamp=NOW()");
Update: Here's my folio table structure
CREATE TABLE `folio` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`publication` varchar(255) DEFAULT NULL,
`productId` varchar(255) DEFAULT NULL,
`timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_folio` (`publication`,`productId`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;
Update 2: Table structure after setting timestamp to not null
CREATE TABLE `folio` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`publication` varchar(255) DEFAULT NULL,
`productId` varchar(255) DEFAULT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_folio` (`publication`,`productId`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
As far as I can see, the problem with your queries might be because you made timestamp field nullable
`timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Try making it NOT NULL - since you have valid default value for it, MySQL won't complain you have not provided the value in the query:
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Also, try renaming timestamp field to something more sane, e.g.:
`changed_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Also, as mentioned in my comments - you don't need to provide all fields in ON DUPLICATE KEY section, but only data fields:
INSERT INTO folio(publication, productId)
VALUES(:publication, :productId)
ON DUPLICATE KEY UPDATE
publication=:publication,
productId=:productId
It is because if MySQL detects you have a duplicate key condition, it won't insert new row, but update the existing one, therefore id column must be left intact.
UPDATE
Seems that not updating the timestamp column is a documented behavior - MySQL manual for TIMESTAMP columns
Citing the needed paragraph:
If the column is auto-updated, it is automatically updated to the current timestamp when the value of any other column in the row is changed from its current value. The column remains unchanged if all other columns are set to their current values. To prevent the column from updating when other columns change, explicitly set it to its current value. To update the column even when other columns do not change, explicitly set it to the value it should have (for example, set it to CURRENT_TIMESTAMP).
So, you are meeting all conditions :) - when you insert the record the timestamp should be populated correctly.
But when you provide the duplicate values on order to update the timestamp, MySQL sees you set the values that already exist in the row (otherwise it wouldn't be duplicate), therefore it does not update the timestamp column.
So, the solution is straightforward and already found by you - update the timestamp column explicitly whenever you provide the duplicate values, e.g.:
INSERT INTO folio(publication, productId)
VALUES(:publication, :productId)
ON DUPLICATE KEY UPDATE
`timestamp` = NOW()
Anyway, making timestamp NOT NULL won't hurt.
If the new INSERT values are the same as the old values in the duplicate row then apparently MySQL does not perform the UPDATE, therefore the ON UPDATE CURRENT_TIMESTAMP is not fired. :(
So, as an awkward workaround, you can add a dummy field to your table, forcing the UPDATE to occur (in the case of a duplicate id):
$statement = $this->connection->prepare("
INSERT INTO folio(publication, productId)
VALUES(:publication, :productId)
ON DUPLICATE KEY UPDATE
id=LAST_INSERT_ID(id), publication=:publication, productId=:productId,
dummy = NOT dummy
");
...as suggested in the User Comments here: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
it's just
insert into your_table (a, b) values (?, ?) on duplicate key update created = current_timestamp
For better or worse, MySQL does not , in any way, default-update timestamps in the case of insert-uniquely type calls.
it does not matter which of the three, insert-on-dupe, replace, insert-ignore you are using
it does not make any difference whatsoever which settings or qualities you use on the fields, table or anything else
It just has to be done manually by adding created = current_timestamp on the end.
Unfortunately that's it!

Datetime and Timestamp Issue while creating MYSQL Table

I am trying to create mysql table in PhpMyAdmin in Hostgator server with the following information but it is showing error
Error : #1067 - Invalid default value for 'CreatedDate'
Table
CREATE TABLE `tbl_sample` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Domain` varchar(100) DEFAULT NULL,
`ClickUrl` varchar(600) DEFAULT NULL,
`CreatedDate` datetime NULL DEFAULT now(),
`ModifyDate` timestamp NULL DEFAULT NULL on update now(),
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
The purpose of table is I need to enter only 'Domain' and 'ClickUrl' data using insert command remaining Id(autoincrement),CreatedDate(current date when inserting row),ModifyDate(when update the row) will automatically insert.
The above table is executed successfully in mysql environment in my local system but it is not executing in the mysql environment in hostgator
Check this link]1
Problem with creating Two column with timestamps. have to use trigger to get it done.

PHP/SQL Date Created vs Date Modified

I am working on a function that compares the date created and date modified of images and return the status of each case with PHP + MySQL. However, I realized that the data i'm trying to compare both end up using the CURRENT_TIMESTAMP in MySQL so whenever they are updated they end up having the same dates.
Is there a way to just only save the first date the data is inserted into the database (date created) so it doesn't change based on date modified?
Any help is appreciated, thanks in advance!
UPDATE:
my timestamp columns are configured using "DEFAULT CURRENT_TIMESTAMP" not the "ON UPDATE CURRENT_TIMESTAMP" option. Any other work arounds?
UPDATE2:
Please see below for my table definition.
CREATE TABLE IF NOT EXISTS `images` (
`id` varchar(50) NOT NULL,
`patientid` varchar(8) NOT NULL,
`caseid` varchar(25) NOT NULL,
`image_name` varchar(256) NOT NULL,
`status` int(1) unsigned NOT NULL,
`comments` varchar(4000) DEFAULT NULL,
`mod_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Seems like your timestamp columns are configured with "ON UPDATE CURRENT_TIMESTAMP" option, which automatically updates them.
As there does not seem a way to change this on a column, you have to create a new column without that option.
See the TIMESTAMP manual for details visit timestamp-initialization

'created at' and 'updated at' fields

This seems like a really simple one but I'm struggling to figure it out. I want a column in my database that lists when a record was first created and another column that says when it was updated. It's my understanding I should be able to do all this just using MySQL. All help is appreciated :)
This stinks still no answer, reasons I'm already starting to miss Ruby on Rails...
You will probably need to use a combination of the Datetime datatype and the Timestamp data type. I would set my created column as a DateTime with a DEFAULT NOW(), and my updated column as a Timestamp with DEFAULT CURRENT_TIMESTAMP and an ON UPDATE CURRENT_TIMESTAMP attribute.
Here are the docs for the Timestamp dt:
http://dev.mysql.com/doc/refman/5.0/en/timestamp.html
In a CREATE TABLE statement, the first TIMESTAMP column can be declared in any of the following ways:
With both DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP clauses, the column has the current timestamp for its default value, and is automatically updated.
With neither DEFAULT nor ON UPDATE clauses, it is the same as DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP.
With a DEFAULT CURRENT_TIMESTAMP clause and no ON UPDATE clause, the column has the current timestamp for its default value but is not automatically updated.
With no DEFAULT clause and with an ON UPDATE CURRENT_TIMESTAMP clause, the column has a default of 0 and is automatically updated.
With a constant DEFAULT value, the column has the given default and is not automatically initialized to the current timestamp. If the column also has an ON UPDATE CURRENT_TIMESTAMP clause, it is automatically updated; otherwise, it has a constant default and is not automatically updated.
To fulfill your question and for others viewing this question, here is the answer. Note this was written for MySQL 5.x.
DROP TABLE IF EXISTS `test1`;
CREATE TABLE `test1` (
`id` INT NULL AUTO_INCREMENT ,
`name` varchar(50) NOT NULL ,
`created` DATETIME ,
`updated` DATETIME ,
PRIMARY KEY (`id`),
INDEX (`name`)
);
DELIMITER $$
DROP TRIGGER IF EXISTS `test1_created`$$
CREATE TRIGGER `test1_created` BEFORE INSERT ON `test1`
FOR EACH ROW BEGIN
SET NEW.`created` = UTC_TIMESTAMP();
SET NEW.`updated` = UTC_TIMESTAMP();
END;
$$
DROP TRIGGER IF EXISTS `test1_updated`$$
CREATE TRIGGER `test1_updated` BEFORE UPDATE ON `test1`
FOR EACH ROW BEGIN
SET NEW.`updated` = UTC_TIMESTAMP();
END;
$$
DELIMITER ;
Note
You could use TIMESTAMP for the updated column which would have automatically updated the value thus not requiring the BEFORE UPDATE trigger, however TIMESTAMP has a range from 1970 to 2038 which is fast approaching and I like to think my applications will live forever :). Although TIMESTAMP is only 4bytes while DATETIME is 8bytes.
TIMESTAMP range '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC
DATETIME range '1000-01-01 00:00:00' to '9999-12-31 23:59:59'
From the MySQL 5.0 Certification Guide:
CREATE TABLE ts_test5 (
created TIMESTAMP DEFAULT 0,
updated TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
data CHAR(30)
);
To control the initialization and update behaviour of a TIMESTAMP column, you add either or both of the DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP attributes to the column defintion when creating the table with CREATE TABLE...
and
...if you do not specify either of the DEFAULT CURRENT_TIMESTAMP or ON UPDATE CURRENT_TIMESTAMP attributes when creating a table, MySQL automatically assigns BOTH to the first TIMESTAMP column
Also
you cannot use DEFAULT CURRENT_TIMESTAMP with one column and ON UPDATE CURRENT_TIMESTAMP with another
If you can't use the timestamp fields with default attributes that Paul W has suggested, you can use AFTER INSERT and AFTER UPDATE triggers to populate the fields.
You will need two fields "Created" and
"Updated" with type datetime. When a
new entry is inserted then insert
"Created" with current time stamp.
When a update is happening insert
"Updated" with the current time stamp,
and let the "Created" field remain as
it is.
For current time stamp you can use
NOW() in your mysql query.

Categories