Can CURRENT_TIMESTAMP change within an INSERT or UPDATE command? - mysql

I have a table with a few dates (among other things) that look like this:
CREATE TABLE message (
created_on DATEIMTE NOT NULL DEFAULT CURRENT_TIMESTAMP,
send_on DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
modified_on DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
status CHAR NOT NULL DEFAULT 'V',
status_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
...
);
When I do an INSERT INTO, I generally do not define the modified_on field since the default makes sense. I may change the send_on value if I do not want my message to be sent immediately.
So an insertion could look like this:
INSERT INTO message
(send_on)
VALUES ('2017-08-31 14:31:22');
Later, the user may ask to change the send_on field. At that point, I run an UPDATE statement as follow:
UPDATE message
SET send_on = <user-defined-date>,
modified_on = CURRENT_TIMESTAMP
WHERE id = 123;
This case is fine since I modified only one date.
Now, at the time the user makes a modification, I may have to also change the status field. That would translate into something like this:
UPDATE message
SET send_on = <user-defined-date>,
modified_on = CURRENT_TIMESTAMP,
status = <new-status>,
status_date = CURRENT_TIMESTAMP
WHERE id = 123;
In that last UPDATE statement and less obvious, in the INSERT INTO statement above, I am setting more than one DATETIME field to the value CURRENT_TIMESTAMP (2 in that UPDATE, 3 in the INSERT INTO through the DEFAULT definitions).
My question is: will all the columns assigned the value CURRENT_TIMESTAMP always receive the exact same value whenever it gets used more than once? Or will each column determine the value of CURRENT_TIMESTAMP once it gets executed and hence, could be a second later (if we were a few ms away from the next second, it can easily happen.)
So far I have not seen a problem, but that does not mean it could not happen. Is that specific case properly documented somewhere in the MySQL reference?

According to the documentation,
NOW() returns a constant time that indicates the time at which the statement began to execute. (Within a stored function or trigger, NOW() returns the time at which the function or triggering statement began to execute.) This differs from the behavior for SYSDATE(), which returns the exact time at which it executes.
So current_timestamp (which is a synonym for now()) will have the same value even if the query runs for hours. It is so relevant that it will actually even keep that value if the query gets replicated to a different server.

Related

mysql datetime default 0001-01-01 00:00:00 on update 0001-01-01 00:00:00

I have a table, let's call it employees, that sends data to a web server, whenever this happens a datetime field is updated with a current_timestamp.
Now, when a record changes, I want to reset the datetime field to 0001-01-01 00:00:00 so that it will send the new information again.
Is it possible to do something like
DEFAULT 0001-01-01 00:00:00 ON UPDATE 0001-01-01 00:00:00
instead of
DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
on update only supports current_timestamp; no other value is allowed. See Automatic Initialization and Updating for TIMESTAMP and DATETIME:
Use of DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP is specific to TIMESTAMP and DATETIME. The DEFAULT clause also can be used to specify a constant (nonautomatic) default value; for example, DEFAULT 0 or DEFAULT '2000-01-01 00:00:00'.
You can either use an after update trigger, but the common solution is to use another column and set the value to current_timestamp on export and compare that to the latest update:
create table tablename (
...
updated_at datetime(6) default current_timestamp(6)
on update current_timestamp(6),
exported_at datetime(6) default '0001-01-01 00:00:00'
)
To get all rows that needs to be exported, use
select * from tablename where exported_at <> updated_at for update;
To mark something as updated after an export, you then use
update tablename set exported_at = current_timestamp(6);
(Everything inside a transaction of course)
Thanks to #Lightness Races in Orbit for pointing out that it's not obvious why to use datetime(6) instead of datetime: per default, mysql uses datetime with second precision. That is usually not a problem - but for this application of detecting changes it would miss updates that were applied within 1 second of the export, and thus would have a slightly different effect than "resetting the column on every update to a value that marks that update". This only works for mysql 5.6.4 and above. Prior to that, use a trigger if you need that precision.

Force MySQL to update TIMESTAMP column

I believe I have set my 5.6.17 ver MySQL server to recognize IANA TZ Databases as evidenced by
a system_time_zone variable being set to "Pacific Daylight Time"
a time_zone variable being set to UTC
NOW(), giving me a standard SQL format date time
I thought that that would be sufficient to create an auto updating time stamp field, but, if I create a table via:
CREATE TABLE test (
id SERIAL,
stamp TIMESTAMP,
stuff VARCHAR(255)
);
INSERT INTO test ( stuff ) VALUES ( 'abc' );
SELECT * FROM test;
records seem to be created with NULL in the stamp field:
id stamp stuff
1 NULL abc
I thought that maybe the date gets entered only when doing an update, but when I update:
UPDATE test SET note = 'xyz' WHERE id = 1;
still the stamp is NULL
id stamp stuff
1 NULL xyz
I attempted to change the create as
stamp TIMESTAMP DEFAULT NOW(),
which provides a proper value, but the stamp field remains unchanged when I update (even minutes later).
I also attempted to use
stamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
which, also, gave me an initial value, but never changed when updating.
Also, attempting to append AUTO_INCREMENT didn't seem to work for me. Did I mention that I'm a MySQL newb?
How do I force my TIMESTAMP field to fill at creation and modify when updated?
A field with type TIMESTAMP is also just another field without any special properties like auto initialization or update.
DEFAULT CURRENT_TIMESTAMP only sets the current timestamp when you create the row.
You are looking for the property ON UPDATE CURRENT_TIMESTAMP. This will set the timestamp each time you update the row, given that at least one of the row's values actually changes.
For more infos, have a look at the MySQL docs regarding Automatic Initialization and Update for TIMESTAMP.
Bottom line, create your table like this and stamp will always give you the timestamp of the last change:
CREATE TABLE test (
id SERIAL,
stamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
stuff VARCHAR(255)
);
Sorry can't comment without enough reputation, and I don't know what is IANA TZ Database
But you can try to add On update CURRENT_TIMESTAMP when you create the table:
CREATE TABLE test (
id SERIAL,
stamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,`
stuff VARCHAR(255)
)
it is quite simple
update table set fieldname=now() where fieldname = value;
here we assume that field we try to update is timestamp type field

MYSQL Timestamp field inserting NULL values

I have a table with the below column
`update_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
I have two databases set up using replication. On master while inserting null to the above column, Current time stamp is inserted.
But the same record on being replicated to the slave gives error. Error is that Null value is not permitted for the column
The only difference is that in slave DB, the specific column is indexed in the table.
Mysql reference has the below line
By default, TIMESTAMP columns are NOT NULL, cannot contain NULL values, and assigning NULL assigns the current timestamp.
So i expect the column to get the current time stamp
The data is put to master through spring.
Is this an expected behaviour?
tl;dr
The NOT NULL is permitting you to pass a null value which would normally become current_timestamp.
Original
Its inserted as "null". INSERT INTO table Values(null);
That's forbidden due to the NOT NULL requirement (the point with NOT NULL is to forbid null values) -- you're not suppose to mention the value. Skip the value and the default value will take it's correct place.
Let's take a look at the docs:
In addition, you can initialize or update any TIMESTAMP column to the current date and time by assigning it a NULL value, unless it has been defined with the NULL attribute to permit NULL values.
You are permitting null values because of your NOT NULL requirement. In order for your argument to be valid then you need to remove it.
Found the issue. The flag
explicit_defaults_for_timestamp
was not set in replication. Setting this solves the problem

How to prevent timestamp fields to update its value when updating a record

Lets say I enter this way a record
"insert into table (value,time) VALUES ('4',NOW())"
And this is how I update a value
"update table set value = '5' WHERE id = '1'"
The problem is that with the last query, the time value gets updated with the current_timestamp again, so the time is wrong.
How can I prevent this? (I want time's value to remain the current_timestamp when was inserted, not updated)
PD: I tried to remove the value CURRENT_TIMESTAMP from the row using sqlBuddy but it gets applied again, like if no changes where saved..
You can simply add in the current value of the field in your update query like this:
update table set value = '5', timestamp_value = timestamp_value WHERE id = '1'
Just make the field a DateTime field with a default value of CURRENT_TIMESTAMP. So it will be set upon creation of a new record but updated only when you want.
You should have the default value set to CURRENT_TIMESTAMP
CREATE TABLE t1 (
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
This should ease your pain.
TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP remove on update CURRENT_TIMESTAMP attribute.
It works on PhpmyAdmin.

Mysql - when trying to UPDATE a timestamp column. It fails to update

I think I may have encountered a bug in mysql, or is it just me doing it wrong.
I've been using the same specific queries for the last four months and just today it stopped working somehow. I can't see the problem.
I'm executing these queries in the mysql console it works great, and the field is being updated. but when these queries are being executed by PHP it fails.
After insertion of a record into a table(with two timestamp fields), I'm trying to update a specific timestamp column.
But unfortunately it fails to update the column.
The query goes well(no errors), but still the value in the timestamp column stays the same. That's weird, cause when I'm leaving the initial column value as NULL, the update query succeed.
Columns :
START_DATETIME, END_DATETIME - are "timestamp" type.
Insert:
INSERT INTO TABLE1(START_DATETIME, END_DATETIME, RESPONSE)
VALUES(NOW(), NOW(), 'STARTED')
Insert is done successfully. id is 123
The update query is normal like any other query:
UPDATE TABLE1
SET END_DATETIME = NOW(), RESPONSE='ENDED'
WHERE ID = 123
Update fails, END_DATETIME doesn't get the NOW() value.
Can be reproduced with this:
CREATE TABLE TABLE1
(
id int auto_increment,
start_datetime timestamp,
end_datetime timestamp,
response varchar(100),
primary key(id)
);
You probably have defined the first timestamp column (the START_DATETIME one) to be auto-inserted and auto-updated with the CURRENT_TIMESTAMP value (which is the same as NOW().
Notice that if you don't explicitedly state anything about the TIMESTAMP columns in the CREATE TABLE script, the first one of them gets by default this behaviour/attributes. Read the MySQL documentation about this Automatic Initialization and Updating for TIMESTAMP, where it states:
With neither DEFAULT CURRENT_TIMESTAMP nor ON UPDATE CURRENT_TIMESTAMP, it is the same as specifying both DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP.
So, if you do a SHOW CREATE TABLE tableName, you'll have something like this:
CREATE TABLE table1
( ...
, START_DATETIME TIMESTAMP NOT NULL
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
, ...
) ;
You should alter the column definition to not be auto_updated, if you don't want this behaviour:
ALTER TABLE table1
MODIFY COLUMN
START_DATETIME TIMESTAMP NOT NULL
DEFAULT CURRENT_TIMESTAMP ;
After looking into this more this is what I'd expect if the first table has ON UPDATE CURRENT_TIMESTAMP as it is being automatically set by the update to the second record.
I don't think that this can have been working previously;
to fix it:
ALTER TABLE TABLE1
CHANGE COLUMN start_datetime start_datetime TIMESTAMP NULL DEFAULT NULL AFTER id,
CHANGE COLUMN end_datetime end_datetime TIMESTAMP NULL DEFAULT NULL AFTER start_datetime;
If you want date time values the TIMESTAMP isn't much good for this as it is useful for auto-updating values as the TIMESTAMP data type offers automatic initialization and updating to the current date and time. For more information, see Automatic Initialization and Updating for TIMESTAMP
If you need a field you can manage yourself then one of the other types
DATE
DATETIME
may be more appropriate, see 11.3.1. The DATE, DATETIME, and TIMESTAMP Types
This is a problem with timestamp type, If you change both the column to datetime, you will get what you are expecting