MySQL (Workbench?) alters my scripts - mysql

I am creating a table into my MySQL database with this script, using MySQL Workbench:
CREATE TABLE `schema`.`Foo` (
[..],
`CreationDate` TIMESTAMP NOT NULL,
`LastUpdateDate` TIMESTAMP NOT NULL,
[..]
);
The problem is that at each commit (including UPDATE statements), the column CreationDate of the impacted rows is modified.
Using MySQL Workbench, I reverse engineered the table and get the following creation script:
CREATE TABLE `Foo` (
[..],
`CreationDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`LastUpdateDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
[..]
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
What the f***?
What kind of configuration within the server can alter my script this way? How can I create my table without these constraints?
I am using MySQL Workbench 6.3.8 Build 1228 CE (64 bits) Community and the server is 5.5.55.0+deb, running on Debian.

If you don't specify a default value, MySQL will pick one for you.
https://dev.mysql.com/doc/refman/5.7/en/data-type-defaults.html
In particular, you've hit these (emphasis mine):
For date and time types other than TIMESTAMP, the default is the appropriate “zero” value for the type. This is also true for TIMESTAMP if the explicit_defaults_for_timestamp system variable is enabled (see Section 5.1.5, “Server System Variables”). Otherwise, for the first TIMESTAMP column in a table, the default value is the current date and time. See Section 11.3, “Date and Time Types”.

Related

Multiple timestamps/datetime with default for SQL 5.5 AND 5.6

Alright, I'm running into a problem with my SQL create table. I work off two different severs, a WAMP sever on my computer for testing, which runs sql 5.6 something, and my online host who don't update very often and are running off 5.5 something. Because of this I'm having a issues with my create table.
my table SQL looks like:
CREATE TABLE some_table
(
user_id INT(6) UNSIGNED AUTO_INCREMENT,
member_till DATETIME DEFAULT CURRENT_TIMESTAMP,
banned_till DATETIME DEFAULT CURRENT_TIMESTAMP,
status ENUM('inactive', 'active') DEFAULT 'inactive',
PRIMARY KEY(user_id)
) ENGINE=InnoDB
This works on my localhost 5.6 server, but my online 5.5 server I get the error "#1067 - Invalid default value for 'member_till'" because 5.5 doesn't allow defaults on DATETIME fields.
So I tried this:
CREATE TABLE some_table
(
user_id INT(6) UNSIGNED AUTO_INCREMENT,
member_till TIMESTAMP NOT NULL,
banned_till TIMESTAMP NOT NULL,
status ENUM('inactive', 'active') DEFAULT 'inactive',
PRIMARY KEY(user_id)
) ENGINE=InnoDB
This works fine on my online 5.5 server, but on my local host 5.6 server when I try to insert a user I get the error "General error: 1364 Field 'member_till' doesn't have a default value".
So I need a solution that works on both servers. Honestly it doesn't matter what time stamp is placed in the fields as the default value is just a place holder, but it has to be valid date-time format that is on or before the sign up date.
P.S. The query is ran using a PHP PDO script encase that makes any difference.

How to update date field automatically from a timestamp field in Mysql 5.5?

I have an InnoDB table with a timestamp in it, and I wish to have another field which carries only the date part of the timestamp, so that I can create an index on it. (My temporal queries will always be bound by date, so having an index with high cardinality on the timestamp is not really needed.)
Is it possible to have the date field update automatically ON UPDATE from the timestamp field (similar to how CURRENT_TIMESTAMP works)?
I tried the following but it MySQL says I have an error in my SQL syntax.
CREATE TABLE test_table (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`full_ts` timestamp NULL DEFAULT NULL COMMENT 'The full timestamp',
`only_date` date NULL DEFAULT NULL ON UPDATE date(full_ts) COMMENT 'This field carries only the date part of the full timestamp for better indexing.',
PRIMARY KEY (`id`),
KEY `ONLY_DATE_IDX` (`only_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I could of course update both fields everywhere in the code, but it would be cleaner if the only_date field was a slave of the full_ts field, updated and kept consistent by the database.
I know that in MySQL 5.7.5 there was a new feature added for stored generated columns, which seem to do exactly this. Unfortunately it is not possible to upgrade the database version at the moment.
Is there a way to achieve this in MySQL 5.5?
This will update the "only_date" column when you update the "full_ts" column
CREATE TRIGGER `autoDate` BEFORE UPDATE ON `test_table` FOR EACH ROW BEGIN
SET NEW.only_date=DATE(NEW.full_ts);
END
EDIT:
For further reading on triggers, please refer to https://dev.mysql.com/doc/refman/5.5/en/create-trigger.html
Also worth reading about triggers https://dev.mysql.com/doc/refman/5.5/en/faqs-triggers.html

What is the reason why MySQL is telling me "Invalid default value for 'postdate'"?

I have 2 Windows servers running MySQL, one of them running version 5.1 and the other running version 5.7. I am trying trying to copy a database from the MySQL 5.7 over to the 5.1 on the other server and believe it's the difference in versions (new syntax in 5.7?) that is causing this error, but I could be wrong.
After Exporting through phpMyAdmin the database I in the 5.7 version and trying to Import in the 5.1 version I'm getting the error
MySQL said: Documentation #1067 - Invalid default value for
'postdate'
on the command
CREATE TABLE IF NOT EXISTS `jobs` (
`id` mediumint( 9 ) NOT NULL ,
`title` varchar( 200 ) DEFAULT NULL ,
`descr` varchar( 5000 ) DEFAULT NULL ,
`postdate` datetime DEFAULT CURRENT_TIMESTAMP
) ENGINE = InnoDB AUTO_INCREMENT =5 DEFAULT CHARSET = utf8mb4;
Any idea why?
In 5.1, the default value has to be a constant value (e.g. NULL is acceptable) except for the timestamp type where current_timestamp is allowed. I.e., for a date or datetime you cannot use current_date, now or current_timestamp.
So you either stick to the datetime type for your postdate column and you have to give up current_timestamp as a default value (you can maybe set up a trigger for the purpose, see examples here), or - depending on your requirements - consider using timestamp (which has a different range of values).
The corresponding section of the manual says:
With one exception, the default value must be a constant; it cannot be
a function or an expression. This means, for example, that you cannot
set the default for a date column to be the value of a function such
as NOW() or CURRENT_DATE. The exception is that you can specify
CURRENT_TIMESTAMP as the default for a TIMESTAMP column.

MySQL column type "TIMESTAMP" implicitly includes "NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"

I've just spent a couple of hours tracking down this bug. Given the following SQL:
DROP DATABASE IF EXISTS db;
CREATE DATABASE db;
CREATE TABLE db.tbl (t1 TIMESTAMP) ENGINE=INNODB;
SHOW CREATE TABLE db.tbl;
The last line shows me:
'CREATE TABLE `tbl` (
`t1` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1'
Where on earth does the NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP come from? I didn't write any of that, and I very much do not want any of that, and I'm kinda lost for words that MySQL would make such a presumption.
Do I have some insane obscure configuration option turned on/off? Is this default behavior? It is a bug? In any case, how do I make MySQL behave sanely?
In MySQL 5.6.5 there are several updates regarding this initialization, you can see on this link (Automatic Timestamp Properties Before MySQL 5.6.5).
If you're using MySQL <= 5.6.5, in order to ignore this initialization you need to set the DEFAULT value to 0 or NULL with NULL allowed.
CREATE TABLE tbl
(
field1 TIMESTAMP DEFAULT 0,
field2 TIMESTAMP NULL DEFAULT NULL
)
If you're using MySQL >= 5.6.6, there is parameter called explicit_defaults_for_timestamp which is disabled by default. You can enable this setting or set the DEFAULT value to 0 or NULL, same approach for previous MySQL versions.
If you're using MySQL >= 8.0.2, then explicit_defaults_for_timestamp is enabled by default. This disables the non-standard behaviour (thankfully). Also, MySQL generates a warning when you disable this setting. So, for instance, if you don't define DEFAULT value for a TIMESTAMP column, it is automatically set to NULL.
Thos are default values which are being used even if not explicitly stated in the CREATE statement. If you want to avoid both, use t1 TIMESTAMP DEFAULT 0 or ts1 TIMESTAMP NULL DEFAULT NULL
Update
Prior to MySQL 5.6.5 you could only use TIMESTAMP in case you wanted to have column that is automatically updated when row is changed. Unfortunately this functionality was limited to MyISAM and isn't available on InnoDB tables.
MySQL 5.6.5 allows this with DATETIME as well. See other posts on this site for more details

MySQL Workbench: how do I set up "ON UPDATE" and CURRENT_TIMESTAMP?

SEE: Update timestamp column in Application or Database?
I'm trying to model something similar in Workbench, but I don't know where to set the "ON UPDATE" part. The best I can get is the following:
-- -----------------------------------------------------
-- Table `foo`.`test`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `foo`.`test` ;
CREATE TABLE IF NOT EXISTS `foo`.`test` (
`test_id` INT NOT NULL ,
`date_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
`date_updated` TIMESTAMP NOT NULL DEFAULT 0 ,
PRIMARY KEY (`test_id`) )
ENGINE = InnoDB;
Where do I go in Workbench to set up this ON UPDATE part?
Also, I have a rule that all timestamps stored in the database should be UTC. How do I make CURRENT_TIMESTAMP, NOW, etc. be UTC?
I am using MySQL Workbench 5.2.35. Open create/alter table panel, switch to the columns tab, right click on the timestamp field; there you can see possible default and on update options.
Important note: You can use CURRENT_TIMESTAMP as default or updated value for only a single column in a table!
Regarding the UTC question, you can have a look at this question. There is an accepted solution there.
I would suggest you to read MySQL reference manuals as well for Timestamp data type and NOW() function.
Here is what I do with MySQL Workbench
Data Type: TIMESTAMP
Default: CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
By default MySQL sets the first timestamp field to CURRENT_TIMESTAMP on every UPDATE or INSERT statement. I go about designing my schema in a way so that updated_at is first timestamp field, so that I don't have to explicitly specify it.