How to set DEFAULT ON UPDATE CURRENT_TIMESTAMP in mysql with sqlalchemy? - mysql

I am creating table with sqlalchemy.
user = Table('users', Metadata,
Column('datecreated', TIMESTAMP,
server_default=text('CURRENT_TIMESTAMP')),
Column('datemodified', TIMESTAMP,
server_onupdate=text('CURRENT_TIMESTAMP')),
)
But this will not set DEFAULT ON UPDATE CURRENT_TIMESTAMP.
I checked out How do you get SQLAlchemy to override MySQL "on update CURRENT_TIMESTAMP" but that will for literal I need to wire that in create table definition.

You can hijack the server_default to set also the ON UPDATE:
Column('datemodified', TIMESTAMP,
server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))
This generates the following column entry:
datemodified TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
However, Mchl's answer still applies: There can be only one automated TIMESTAMP column in a table (http://dev.mysql.com/doc/refman/5.5/en/timestamp.html)
Also note that the order of the columns is of importance! If you have a TIMESTAMP column without DEFAULT and ON UPDATE modifiers, and it is the first TIMESTAMP column in your table,
it automatically will be set to DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP. (http://dev.mysql.com/doc/refman/5.5/en/timestamp.html)
So this is fine:
Column('datemodified', TIMESTAMP,
server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))
Column('datecreated', TIMESTAMP)
while this is not:
Column('datecreated', TIMESTAMP)
Column('datemodified', TIMESTAMP,
server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))
In order to set the `datecreated' to the current time during first entry of a row, just set its value explicitly to NULL. Again, from http://dev.mysql.com/doc/refman/5.5/en/timestamp.html:
By default, TIMESTAMP columns are NOT NULL, cannot contain NULL
values, and assigning NULL assigns the current timestamp.

If you're on MySQL 5.6 or later please scroll down for the relevant answer. Users of older versions, please read this one.
Until MySQL 5.6. in one table, you can only have one 'automated' TIMESTAMP column.
From: http://dev.mysql.com/doc/refman/5.5/en/timestamp.html
For one TIMESTAMP column in a table, you can assign the current
timestamp as the default value and the auto-update value. It is
possible to have the current timestamp be the default value for
initializing the column, for the auto-update value, or both. It is not
possible to have the current timestamp be the default value for one
column and the auto-update value for another column.

This worked on Mysql 8
sa.Column('created_at', sa.TIMESTAMP, server_default=func.now()),
sa.Column('updated_at', sa.TIMESTAMP, server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))
For some reason the server_onupdate options was not working.

from sqlalchemy.sql import func
Column('datemodified',
TIMESTAMP,
server_onupdate=text(
' ON UPDATE '.join([str(func.current_timestamp())] * 2)))
This way you use SQLAlchemy's inner func.current_timestamp() function.

If all you want is DEFAULT CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP in MySQL, then just setting the TIMESTAMP column in sqlalchemy to be non-nullable works
Column(TIMESTAMP, nullable=False)

Related

How do I insert current date as a column in a mysql table that will automatically update [duplicate]

If I have a column in a table of type TIMESTAMP and has as default: CURRENT_TIMESTAMP does this column get updated to the current timestamp if I update the value
of any other column in the the same row?
It seems that it does not but I am not sure if this is what should happen.
I can not understand what this means (from MySQL documentation):
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]2
Give the command SHOW CREATE TABLE whatever
Then look at the table definition.
It probably has a line like this
logtime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
in it. DEFAULT CURRENT_TIMESTAMP means that any INSERT without an explicit time stamp setting uses the current time. Likewise, ON UPDATE CURRENT_TIMESTAMP means that any update without an explicit timestamp results in an update to the current timestamp value.
You can control this default behavior when creating your table.
Or, if the timestamp column wasn't created correctly in the first place, you can change it.
ALTER TABLE whatevertable
CHANGE whatevercolumn
whatevercolumn TIMESTAMP NOT NULL
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP;
This will cause both INSERT and UPDATE operations on the table automatically to update your timestamp column. If you want to update whatevertable without changing the timestamp, that is,
To prevent the column from updating when other columns change
then you need to issue this kind of update.
UPDATE whatevertable
SET something = 'newvalue',
whatevercolumn = whatevercolumn
WHERE someindex = 'indexvalue'
This works with TIMESTAMP and DATETIME columns. (Prior to MySQL version 5.6.5 it only worked with TIMESTAMPs) When you use TIMESTAMPs, time zones are accounted for: on a correctly configured server machine, those values are always stored in UTC and translated to local time upon retrieval.
I think you have to define the timestamp column like this
CREATE TABLE t1
(
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
See here
An auto-updated column is automatically updated to the current timestamp when the value of any other column in the row is changed from its current value. An auto-updated column remains unchanged if all other columns are set to their current values.
To explain it let's imagine you have only one row:
-------------------------------
| price | updated_at |
-------------------------------
| 2 | 2018-02-26 16:16:17 |
-------------------------------
Now, if you run the following update column:
update my_table
set price = 2
it will not change the value of updated_at, since price value wasn't actually changed (it was already 2).
But if you have another row with price value other than 2, then the updated_at value of that row (with price <> 3) will be updated to CURRENT_TIMESTAMP.
Add a trigger in database:
DELIMITER //
CREATE TRIGGER update_user_password
BEFORE UPDATE ON users
FOR EACH ROW
BEGIN
IF OLD.password <> NEW.password THEN
SET NEW.password_changed_on = NOW();
END IF;
END //
DELIMITER ;
The password changed time will update only when password column is changed.
Adding where to find UPDATE CURRENT_TIMESTAMP because for new people this is a confusion.
Most people will use phpmyadmin or something like it.
Default value you select CURRENT_TIMESTAMP
Attributes (a different drop down) you select UPDATE CURRENT_TIMESTAMP

How to make a column update timestamp automatically based on update on selected columns only? [duplicate]

If I have a column in a table of type TIMESTAMP and has as default: CURRENT_TIMESTAMP does this column get updated to the current timestamp if I update the value
of any other column in the the same row?
It seems that it does not but I am not sure if this is what should happen.
I can not understand what this means (from MySQL documentation):
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]2
Give the command SHOW CREATE TABLE whatever
Then look at the table definition.
It probably has a line like this
logtime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
in it. DEFAULT CURRENT_TIMESTAMP means that any INSERT without an explicit time stamp setting uses the current time. Likewise, ON UPDATE CURRENT_TIMESTAMP means that any update without an explicit timestamp results in an update to the current timestamp value.
You can control this default behavior when creating your table.
Or, if the timestamp column wasn't created correctly in the first place, you can change it.
ALTER TABLE whatevertable
CHANGE whatevercolumn
whatevercolumn TIMESTAMP NOT NULL
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP;
This will cause both INSERT and UPDATE operations on the table automatically to update your timestamp column. If you want to update whatevertable without changing the timestamp, that is,
To prevent the column from updating when other columns change
then you need to issue this kind of update.
UPDATE whatevertable
SET something = 'newvalue',
whatevercolumn = whatevercolumn
WHERE someindex = 'indexvalue'
This works with TIMESTAMP and DATETIME columns. (Prior to MySQL version 5.6.5 it only worked with TIMESTAMPs) When you use TIMESTAMPs, time zones are accounted for: on a correctly configured server machine, those values are always stored in UTC and translated to local time upon retrieval.
I think you have to define the timestamp column like this
CREATE TABLE t1
(
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
See here
An auto-updated column is automatically updated to the current timestamp when the value of any other column in the row is changed from its current value. An auto-updated column remains unchanged if all other columns are set to their current values.
To explain it let's imagine you have only one row:
-------------------------------
| price | updated_at |
-------------------------------
| 2 | 2018-02-26 16:16:17 |
-------------------------------
Now, if you run the following update column:
update my_table
set price = 2
it will not change the value of updated_at, since price value wasn't actually changed (it was already 2).
But if you have another row with price value other than 2, then the updated_at value of that row (with price <> 3) will be updated to CURRENT_TIMESTAMP.
Add a trigger in database:
DELIMITER //
CREATE TRIGGER update_user_password
BEFORE UPDATE ON users
FOR EACH ROW
BEGIN
IF OLD.password <> NEW.password THEN
SET NEW.password_changed_on = NOW();
END IF;
END //
DELIMITER ;
The password changed time will update only when password column is changed.
Adding where to find UPDATE CURRENT_TIMESTAMP because for new people this is a confusion.
Most people will use phpmyadmin or something like it.
Default value you select CURRENT_TIMESTAMP
Attributes (a different drop down) you select UPDATE CURRENT_TIMESTAMP

how to alter table to add new column date with default value of current date?

I got confused about the alter.
I have an existing table, register and I want to add a this_date column with default value of current date. is it possible by alter? well it has already have data.
It should be okay.
ALTER TABLE ADD COLUMN this_date DATE DEFAULT CURRENT_DATE;
As long as the new column is nullable and/or has a default value, there shouldn't be a problem.
You can also choose where to put the column, use the keyword after:
ALTER TABLE MyTable ADD `MyColumn` DATETIME AFTER `LastColumn`
This wasn't possible for me on MySQL 5.7. It gives me an error every time.
I can do it with a DATETIME field and NOW() as default, but not with CURRENT_DATE.
ALTER TABLE "TableName" ADD "New_Column_Name" TIMESTAMP DEFAULT now();
On MySQL 5.7, I didn't find a way to use CURRENT_DATE or its synonyms as default.
If your application will always provide values in INSERT statements and you only need a way to add a non-null column to existing data and then set values for existing row, you can work around this by providing a fixed default for the non-null date column
ALTER TABLE MyTable ADD COLUMN MyColumn DATE DEFAULT '2020-01-01'
and then update it to CURRENT_DATE
UPDATE MyTable SET MyColumn = CURRENT_DATE

When is a timestamp (auto) updated?

If I have a column in a table of type TIMESTAMP and has as default: CURRENT_TIMESTAMP does this column get updated to the current timestamp if I update the value
of any other column in the the same row?
It seems that it does not but I am not sure if this is what should happen.
I can not understand what this means (from MySQL documentation):
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]2
Give the command SHOW CREATE TABLE whatever
Then look at the table definition.
It probably has a line like this
logtime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
in it. DEFAULT CURRENT_TIMESTAMP means that any INSERT without an explicit time stamp setting uses the current time. Likewise, ON UPDATE CURRENT_TIMESTAMP means that any update without an explicit timestamp results in an update to the current timestamp value.
You can control this default behavior when creating your table.
Or, if the timestamp column wasn't created correctly in the first place, you can change it.
ALTER TABLE whatevertable
CHANGE whatevercolumn
whatevercolumn TIMESTAMP NOT NULL
DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP;
This will cause both INSERT and UPDATE operations on the table automatically to update your timestamp column. If you want to update whatevertable without changing the timestamp, that is,
To prevent the column from updating when other columns change
then you need to issue this kind of update.
UPDATE whatevertable
SET something = 'newvalue',
whatevercolumn = whatevercolumn
WHERE someindex = 'indexvalue'
This works with TIMESTAMP and DATETIME columns. (Prior to MySQL version 5.6.5 it only worked with TIMESTAMPs) When you use TIMESTAMPs, time zones are accounted for: on a correctly configured server machine, those values are always stored in UTC and translated to local time upon retrieval.
I think you have to define the timestamp column like this
CREATE TABLE t1
(
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
See here
An auto-updated column is automatically updated to the current timestamp when the value of any other column in the row is changed from its current value. An auto-updated column remains unchanged if all other columns are set to their current values.
To explain it let's imagine you have only one row:
-------------------------------
| price | updated_at |
-------------------------------
| 2 | 2018-02-26 16:16:17 |
-------------------------------
Now, if you run the following update column:
update my_table
set price = 2
it will not change the value of updated_at, since price value wasn't actually changed (it was already 2).
But if you have another row with price value other than 2, then the updated_at value of that row (with price <> 3) will be updated to CURRENT_TIMESTAMP.
Add a trigger in database:
DELIMITER //
CREATE TRIGGER update_user_password
BEFORE UPDATE ON users
FOR EACH ROW
BEGIN
IF OLD.password <> NEW.password THEN
SET NEW.password_changed_on = NOW();
END IF;
END //
DELIMITER ;
The password changed time will update only when password column is changed.
Adding where to find UPDATE CURRENT_TIMESTAMP because for new people this is a confusion.
Most people will use phpmyadmin or something like it.
Default value you select CURRENT_TIMESTAMP
Attributes (a different drop down) you select UPDATE CURRENT_TIMESTAMP

SQL - Creating a Table with Two Timestamp Column with No Default Value

I want to create a table with two column, one "created" and one "modified", with a timestamp type. I don't want them to have a default value. But when I create them, it automatically puts CURRENT_TIMESTAMP as default for at least one of them, and also on update.
How can I just have type timestamp with no default or on update value for any of my column?
Edit: I use MySQL
If you are using SQL Server, the timestamp type is used for row versioning, not for storing an actual date or time value. See MSDN.
You could create the columns with a datetime datatype and then set your created and modified values with triggers.
CREATE TRIGGER trg_SetDateCreated ON MyTable
FOR INSERT AS
UPDATE MyTable
SET created = CURRENT_TIMESTAMP
WHERE MyTable.id = (SELECT Id FROM Inserted);
GO
CREATE TRIGGER trg_SetDateModified ON MyTable
FOR UPDATE AS
UPDATE MyTable
SET modified = CURRENT_TIMESTAMP
WHERE MyTable.id = (SELECT Id FROM Inserted);
GO