Related
In fact there are so many similar questions, I could not solve this problem.
I am using codeigniter framework. When I call insert method of ActiveRecord by passing a php object, it send all properties either by its value or as null. It causes cannot be null. error.
Table Structure:
CREATE TABLE `scheduledTasks` (
`id` int(11) NOT NULL,
`type` varchar(255) COLLATE utf8_bin NOT NULL,
`createTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`executionTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ownerUserId` int(11) DEFAULT NULL,
`subjectUserId` text COLLATE utf8_bin,
`detail` text COLLATE utf8_bin,
`isExecuted` int(1) DEFAULT '0'
);
ALTER TABLE `scheduledTasks`
ADD PRIMARY KEY (`id`);
ALTER TABLE `scheduledTasks`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
Query I tried:
INSERT INTO `scheduledTasks` (`id`, `type`, `createTime`, `executionTime`, `ownerUserId`, `detail`, `isExecuted`)
VALUES (NULL, 'QuoteRequest', NULL, NULL, '926', NULL, NULL)
Mysql Version:
+-------------------------+
| VERSION() |
+-------------------------+
| 5.7.17-0ubuntu0.16.04.1 |
+-------------------------+
I have
explicit_defaults_for_timestamp | OFF
and sql mode is
+-------------------------------------------------------------------------------------------------------------------------------------------+
| ##SESSION.sql_mode |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+-------------------------------------------------------------------------------------------------------------------------------------------+
Discussion
The MySQL 5.7 manual states that...
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.
The manual does not say you can do this for DATETIME fields. The best thing to do would be to supply no values in your INSERT query for the createTime and executionTime fields. That should give you the DEFAULT_TIMESTAMP. If that fails, well, I tried.
INSERT INTO `scheduledTasks` (`id`, `type`, `createTime`, `executionTime`, `ownerUserId`, `detail`, `isExecuted`)
VALUES (NULL, 'QuoteRequest', , , '926', NULL, NULL)
Also, keep this in mind about MySQL default values, even though your DATETIME columns do have an explicit DEFAULT clause.
For data entry into a NOT NULL column that has no explicit DEFAULT
clause, if an INSERT or REPLACE statement includes no value for the
column, or an UPDATE statement sets the column to NULL, MySQL handles
the column according to the SQL mode in effect at the time:
If strict SQL mode is enabled, an error occurs for transactional tables and the statement is rolled back. For nontransactional tables,
an error occurs, but if this happens for the second or subsequent row
of a multiple-row statement, the preceding rows will have been
inserted.
If strict mode is not enabled, MySQL sets the column to the implicit default value for the column data type.
Finally, about strict mode in the MySQL Manual:
For STRICT_TRANS_TABLES, MySQL converts an invalid value to the
closest valid value for the column and inserts the adjusted value. If
a value is missing, MySQL inserts the implicit default value for the
column data type. In either case, MySQL generates a warning rather
than an error and continues processing the statement. Implicit
defaults are described in Section 12.7, “Data Type Default Values”.
Conclusion
In summary, if you are in strict mode (which you are, STRICT_TRANS_TABLES) and have DATETIME columns set to NOT NULL DEFAULT CURRENT_TIMESTAMP, and then you supply NULL values during an INSERT, and then subsequently you get a "cannot be NULL" error, ... next time around do not supply values to the DATETIME fields.
If your framework cannot be setup to omit values during INSERT, and changing the SQL mode does not work, then altering the table to use (gasp) TIMESTAMP may be your only option to use NULL in strict mode and have a DEFAULT TIMESTAMP appear.
I've recently taken over an old project that was created 10 years ago. It uses MySQL 5.1.
Among other things, I need to change the default character set from latin1 to utf8.
As an example, I have tables such as this:
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(45) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`last_name` varchar(45) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`username` varchar(127) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`email` varchar(127) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`pass` varchar(20) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL,
`active` char(1) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL DEFAULT 'Y',
`created` datetime NOT NULL,
`last_login` datetime DEFAULT NULL,
`author` varchar(1) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT 'N',
`locked_at` datetime DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`ripple_token` varchar(36) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`ripple_token_expires` datetime DEFAULT '2014-10-31 08:03:55',
`authentication_token` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index_users_on_reset_password_token` (`reset_password_token`),
UNIQUE KEY `index_users_on_confirmation_token` (`confirmation_token`),
UNIQUE KEY `index_users_on_unlock_token` (`unlock_token`),
KEY `users_active` (`active`),
KEY `users_username` (`username`),
KEY `index_users_on_email` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=1677 DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC
I set up my own Mac to work on this. Without thinking too much about it, I ran "brew install mysql" which installed MySQL 5.7. So I have some version conflicts.
I downloaded a copy of this database and imported it.
If I try to run a query like this:
ALTER TABLE users MODIFY first_name varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL
I get this error:
ERROR 1292 (22007): Incorrect datetime value: '0000-00-00 00:00:00' for column 'created' at row 1
I thought I could fix this with:
ALTER TABLE users MODIFY created datetime NULL DEFAULT '1970-01-01 00:00:00';
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0
but I get:
ALTER TABLE users MODIFY first_name varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ;
ERROR 1292 (22007): Incorrect datetime value: '0000-00-00 00:00:00' for column 'created' at row 1
Do I have to update every value?
I wasn't able to do this:
UPDATE users SET created = NULL WHERE created = '0000-00-00 00:00:00'
(on MySQL 5.7.13).
I kept getting the Incorrect datetime value: '0000-00-00 00:00:00' error.
Strangely, this worked: SELECT * FROM users WHERE created = '0000-00-00 00:00:00'. I have no idea why the former fails and the latter works... maybe a MySQL bug?
At any case, this UPDATE query worked:
UPDATE users SET created = NULL WHERE CAST(created AS CHAR(20)) = '0000-00-00 00:00:00'
Changing the default value for a column with an ALTER TABLE statement, e.g.
ALTER TABLE users MODIFY created datetime NULL DEFAULT '1970-01-02'
... doesn't change any values that are already stored. The "default" value applies to rows that are inserted, and for which a value is not supplied for the column.
As to why you are encountering the error, it's likely that the sql_mode setting for your session includes NO_ZERO_DATE.
Reference: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_zero_date
When you did the "import", the SQL statements that did the INSERT into that table were run in a session that allowed for zero dates.
To see the sql_mode setting:
SHOW VARIABLES LIKE 'sql_mode' ;
-or-
SELECT ##sql_mode ;
As far as how to "fix" the current problem, so that the error won't be thrown when you run the ALTER TABLE statement.
Several options:
1) change the sql_mode to allow zero dates, by removing NO_ZERO_DATE and NO_ZERO_IN_DATE. The change can be applied in the my.cnf file, so after a restart of MySQL Server, sql_mode variable will be initialized to the setting in my.cnf.
For a temporary change, we can modify the setting with a single session, without requiring a global change.
-- save current setting of sql_mode
SET #old_sql_mode := ##sql_mode ;
-- derive a new value by removing NO_ZERO_DATE and NO_ZERO_IN_DATE
SET #new_sql_mode := #old_sql_mode ;
SET #new_sql_mode := TRIM(BOTH ',' FROM REPLACE(CONCAT(',',#new_sql_mode,','),',NO_ZERO_DATE,' ,','));
SET #new_sql_mode := TRIM(BOTH ',' FROM REPLACE(CONCAT(',',#new_sql_mode,','),',NO_ZERO_IN_DATE,',','));
SET ##sql_mode := #new_sql_mode ;
-- perform the operation that errors due to "zero dates"
-- when we are done with required operations, we can revert back
-- to the original sql_mode setting, from the value we saved
SET ##sql_mode := #old_sql_mode ;
2) change the created column to allow NULL values, and update the existing rows to change the zero dates to null values
3) update the existing rows to change the zero dates to a valid date
We don't need to run individual statements to update each row. We can update all of the rows in one fell swoop (assuming it's a reasonably sized table. For a larger table, to avoid humongous rollback/undo generation, we can perform the operation in reasonably sized chunks.)
In the question, the AUTO_INCREMENT value shown for the table definition assures us that the number of rows is not excessive.
If we've already changed the created column to allow for NULL values, we can do something like this:
UPDATE `users` SET `created` = NULL WHERE `created` = '0000-00-00 00:00:00'
Or, we can set those to a valid date, e.g. January 2, 1970
UPDATE `users` SET `created` = '1970-01-02' WHERE `created` = '0000-00-00 00:00:00'
(Note that a datetime value of midnight Jan 1, 1970 ('1970-01-01 00:00:00') is a "zero date". That will be evaluated to be '0000-00-00 00:00:00'
I got it fixed by doing this before the query
SET SQL_MODE='ALLOW_INVALID_DATES';
According to MySQL 5.7 Reference Manual:
The default SQL mode in MySQL 5.7 includes these modes: ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, and NO_ENGINE_SUBSTITUTION.
Since 0000-00-00 00:00:00 is not a valid DATETIME value, your database is broken. That is why MySQL 5.7 – which comes with NO_ZERO_DATE mode enabled by default – outputs an error when you try to perform a write operation.
You can fix your table updating all invalid values to any other valid one, like NULL:
UPDATE users SET created = NULL WHERE created < '0000-01-01 00:00:00'
Also, to avoid this problem, I recomend you always set current time as default value for your created-like fields, so they get automatically filled on INSERT. Just do:
ALTER TABLE users
ALTER created SET DEFAULT CURRENT_TIMESTAMP
Instead of
UPDATE your_table SET your_column = new_valid_value where your_column = '0000-00-00 00:00:00';
Use
UPDATE your_table SET your_column = new_valid_value where your_column = 0;
Here what my solution PhpMyAdmin / Fedora 29 / MySQL 8.0 (for example):
set sql_mode='SOMETHING'; doesn't work, command call successful but nothing was change.
set GLOBAL sql_mode='SOMETHING'; change global configuration permanent change.
set SESSION sql_mode='SOMETHING'; change session configuration SESSION variable affects only the current client.
https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html
So I do this :
Get SQL_MODE : SHOW VARIABLES LIKE 'sql_mode';
Result :
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
Remove on the result : NO_ZERO_IN_DATE,NO_ZERO_DATE
Set new configuration : set GLOBAL SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
You can remove or add other mode in the same way.
This is helpful to change global for using and testing frameworks or sql_mode must be specified in each file or bunch of queries.
Adapted from a question ask here : how-can-i-disable-mysql-strict-mode
Example : install latest Joomla 4.0-alpha content.
Edit:
In PhpMyadmin, if you have the control of the server, you can change the sql_mode (and all others parameters) directly in Plus > Variables > sql_mode
I found the solution at https://support.plesk.com/hc/en-us/articles/115000666509-How-to-change-the-SQL-mode-in-MySQL. I had this:
mysql> show variables like 'sql_mode';
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value |
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| sql_mode | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set, 1 warning (0.01 sec)
Notice the NO_ZERO_IN_DATE,NO_ZERO_DATE in the results above. I removed that by doing this:
mysql> SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
Query OK, 0 rows affected, 1 warning (0.00 sec)
Then I had this:
mysql> show variables like 'sql_mode';
+---------------+--------------------------------------------------------------------------------------------------------------+
| Variable_name | Value |
+---------------+--------------------------------------------------------------------------------------------------------------+
| sql_mode | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+---------------+--------------------------------------------------------------------------------------------------------------+
1 row in set, 1 warning (0.01 sec)
After doing that, I could use ALTER TABLE successfully and alter my tables.
SET sql_mode = 'NO_ZERO_DATE';
UPDATE `news` SET `d_stop`='2038-01-01 00:00:00' WHERE `d_stop`='0000-00-00 00:00:00'
My suggestion if it is the case that the table is empty or not very very big is to export the create statements as a .sql file, rewrite them as you wish. Also do the same if you have any existing data, i.e. export insert statements (I recommend doing this in a separate file as the create statements). Finally, drop the table and execute first create statement and then inserts.
You can use for that either mysqldump command, included in your MySQL installation or you can also install MySQL Workbench, which is a free graphical tool that includes also this option in a very customisable way without having to look for specific command options.
Check
SELECT ##sql_mode;
if you see 'ZERO_DATE' stuff in there, try
SET GLOBAL sql_mode=(SELECT REPLACE(##sql_mode,'NO_ZERO_DATE',''));
SET GLOBAL sql_mode=(SELECT REPLACE(##sql_mode,'NO_ZERO_IN_DATE',''));
Log out and back in again to your client (this is strange) and try again
This issue is happening because MYSQL 5.7 introduced default modes like
SELECT ##GLOBAL.sql_mode global, ##SESSION.sql_mode session;
=> ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
Among the default modes, there is a mode NO_ZERO_DATE which prevents you to put the value 0000-00-00 00:00:00 in the datetime column.
Temporary fix would be removing the mode NO_ZERO_DATE/NO_ZERO_IN_DATE from the default modes and keeping the other modes as it is.
SET GLOBAL sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
But once you restart your mysql server, all your temporary settings will be gone and the default modes will be enabled again. To fix this on restart, change the default modes in my.cnf file on your machine.
Refer the docs :- https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#:~:text=To%20set%20the%20SQL%20mode,ini%20(Windows).
My personal opinion :- The right developmental practice would be putting a right datetime value in the column instead of 0000-00-00 00:00:00. So that you don't have to worry about the SQL modes.
You can change the type of created field from datetime to varchar(255), then you can set (update) all records that have the value "0000-00-00 00:00:00" to NULL.
Now, you can do your queries without error.
After you finished, you can alter the type of the field created to datetime.
This is what I did to solve my problem. I tested in local MySQL 5.7 ubuntu 18.04.
set global sql_mode="NO_ENGINE_SUBSTITUTION";
Before running this query globally I added a cnf file in /etc/mysql/conf.d directory. The cnf file name is mysql.cnf and codes
[mysqld]
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ALLOW_INVALID_DATES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
Then I restart mysql
sudo service mysql restart
Hope this can help someone.
I have this error as well after upgrading MySQL from 5.6 to 5.7
I figured out that the best solution for me was to combine some of the solutions here and make something of it that worked with the minimum of input.
I use MyPHPAdmin for the simplicity of sending the queries through the interface because then I can check the structure and all that easily. You might use ssh directly or some other interface. The method should be similar or same anyway.
...
1.
First check out the actual error when trying to repair the db:
joomla.jos_menu Note : TIME/TIMESTAMP/DATETIME columns of old format have been upgraded to the new format.
Warning : Incorrect datetime value: '0000-00-00 00:00:00' for column 'checked_out_time' at row 1
Error : Invalid default value for 'checked_out_time'
status : Operation failed
This tells me the column checked_out_time in the table jos_menu needs to have all bad dates fixed as well as the "default" changed.
...
2.
I run the SQL query based on the info in the error message:
UPDATE jos_menu SET checked_out_time = '1970-01-01 08:00:00' WHERE checked_out_time = 0
If you get an error you can use the below query instead that seems to always work:
UPDATE jos_menu SET checked_out_time = '1970-01-01 08:00:00' WHERE CAST(checked_out_time AS CHAR(20)) = '0000-00-00 00:00:00'
...
3.
Then once that is done I run the second SQL query:
ALTER TABLE `jos_menu` CHANGE `checked_out_time` `checked_out_time` DATETIME NULL DEFAULT CURRENT_TIMESTAMP;
Or in the case it is a date that has to be NULL
ALTER TABLE `jos_menu` CHANGE `checked_out_time` `checked_out_time` DATETIME NULL DEFAULT NULL;
...
If I run repair database now I get:
joomla.jos_menu OK
...
Works just fine :)
I also got
SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect datetime
value: '0000-00-00 00:00:00' for column
error info
Fix this by changing 0000-00-00 00:00:00 to 1970-01-01 08:00:00
1970-01-01 08:00:00 unix timestamp is 0
Make the sql mode non strict
if using laravel go to config->database, the go to mysql settings and make the strict mode false
I had a similar problem but in my case some line had the value NULL.
so first I update the table:
update `my_table`set modified = '1000-01-01 00:00:00' WHERE modified is null
problem solved, at least in my case.
For Symfony users: Add a default to your orm column as follows:
/**
* #var DateTime $updatedAt
*
* #ORM\Column(name="updated_at", type="datetime", nullable=false, options={"default" : "CURRENT_TIMESTAMP"})
*/
My solution
SET sql_mode='';
UPDATE tnx_k2_items
SET created_by = 790
, modified = '0000-00-00 00:00:00'
, modified_by = 0
I tried
SET GLOBAL sql_mode = '';
and, restart
sudo service mysql restart
which works for me
This is incredibly ugly, but it also fixed the problem quickly for me. Your table needs a unique key which you will use to fix the tainted columns. In this example, the primary key is called 'id' and the broken timestamp column is called 'BadColumn'.
Select the IDs of the tainted columns.
select id from table where BadColumn='0000-00-00 00:00:00'
Collect the IDs into a comma-delimited string. Example: 1, 22, 33. I used an external wrapper for this (a Perl script) to quickly spit them all out.
Use your list of IDs to update the old columns with a valid date (1971 through 2038).
update table set BadColumn='2000-01-01 00:00:00' where id in (1, 22, 33)
Reading through the answers, I tried many of them with no change. I still get the error.
I researched it for a bit and found one that actually worked; for me anyway. But if it worked for me, it'll most likely work for everyone. Cause I never find the answers! lol
I'm on Ubuntu 18.04, But I have used other Linux OS's like Fedora, Straight forward Linux, XAMPP, yadda. And this file seemed to be the same on all of them. I'm also using MySQL version 5.7.37-0.
On Ubuntu, I go to /etc/mysql/. In there, you have several conf files, but the one you want is my.cnf.
In my.cnf, you'll have a section labelled [mysqld]. Just below that (I put it before anything else), you'll enter the following:
sql_mode="ONLY_FULL_GROUP_BY,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
Restart you MySQL Server and you should no longer receive that error.
That is the permanent solution. There is a temporary solution by entering the SQL Command--
SET sql_mode="";
--before your INSERT or UPDATE QUERY which contains such date or datetime values as ‘0000-00-00 00:00:00’, but that's a temporary solution that remains in your current session and you'll have to enter it again the next time you log in and have the same issue.
So, the permanent solution seems the way to go.
If you are entering the data manually you may consider removing the values and the zeros on the TIMESTAMP(6).000000 so that it becomes TIMESTAMP. That worked fine with me.
I think you should use current_timestamp() instead of '0000-00-00 00:00:00'
If you just want to set 0000-00-00 to your field without modifying mySQL configuration, then do following:
UPDATE your_table_name SET your_time_field=FROM_UNIXTIME(0) WHERE ...
FROM_UNIXTIME(0) doing the trick.
I have a MySQL oddity I haven't seen before and could use some help.
I have a users table that was created (not by me) with these two fields:
`date_entered` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`date_modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
These are the only 2 timestamp in the table.
However, that's incorrect so I ran this update statement:
ALTER TABLE `users`
CHANGE `date_entered` `date_entered` TIMESTAMP NOT NULL,
CHANGE `date_modified` `date_modified` TIMESTAMP NOT NULL;
This works fine on my localhost (Wampserver MySQL 5.6.17) but does not work on my production machine (Windows MySQL 5.6.16) and keeps defaulting back to having the DEFAULT set for both fields.
Is there something I need to configure in MySQL or somewhere else to get rid of these defaults? I'd like to remove both but especially the ON UPDATE CURRENT_TIMESTAMP since it makes the data wrong.
Thanks!
Why do I get an error message when I import SQL created MySQL workbench?
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL';
-- -----------------------------------------------------
-- Table `$type`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `type` (
`type_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(255) NULL DEFAULT NULL ,
`created_on` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ,
`updated_on` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ,
PRIMARY KEY (`type_id`) )
ENGINE = MyISAM
AUTO_INCREMENT = 1
DEFAULT CHARACTER SET = utf8;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
error message,
#1067 - Invalid default value for 'created_on'
What is wrong with this value - 0000-00-00 00:00:00
Shortly, the answer by wormhit is wrong. Notice 3rd line:
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL';
TRADITIONAL according to the manual is a shortcut that expands to
STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER
So by specifying the mode you actually prohibiting zero dates. In MySQL Workbench 6 go Preferences -> Model: MySQL and remove TRADITIONAL from SQL_MODE to be used in generated scripts.
Also notice that TIMESTAMP is timezone-aware type, whereas DATETIME is not. So depending on timezone settings of machine, MySQL's global and session settings result-sets could vary.
Use DATETIME instead of TIMESTAMP
If the other methods mentioned here don't work, you can try this:
Modify my.ini of the mysql path.
sql-mode="STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER"
How do you set a default value for a MySQL Datetime column?
In SQL Server it's getdate(). What is the equivalant for MySQL? I'm using MySQL 5.x if that is a factor.
IMPORTANT EDIT:
It is now possible to achieve this with DATETIME fields since MySQL 5.6.5, take a look at the other post below...
Previous versions can't do that with DATETIME...
But you can do it with TIMESTAMP:
mysql> create table test (str varchar(32), ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.00 sec)
mysql> desc test;
+-------+-------------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+-------------------+-------+
| str | varchar(32) | YES | | NULL | |
| ts | timestamp | NO | | CURRENT_TIMESTAMP | |
+-------+-------------+------+-----+-------------------+-------+
2 rows in set (0.00 sec)
mysql> insert into test (str) values ("demo");
Query OK, 1 row affected (0.00 sec)
mysql> select * from test;
+------+---------------------+
| str | ts |
+------+---------------------+
| demo | 2008-10-03 22:59:52 |
+------+---------------------+
1 row in set (0.00 sec)
mysql>
CAVEAT: IF you define a column with CURRENT_TIMESTAMP ON as default, you will need to ALWAYS specify a value for this column or the value will automatically reset itself to "now()" on update. This means that if you do not want the value to change, your UPDATE statement must contain "[your column name] = [your column name]" (or some other value) or the value will become "now()". Weird, but true. I am using 5.5.56-MariaDB
In version 5.6.5, it is possible to set a default value on a datetime column, and even make a column that will update when the row is updated. The type definition:
CREATE TABLE foo (
`creation_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
`modification_time` DATETIME ON UPDATE CURRENT_TIMESTAMP
)
Reference:
http://optimize-this.blogspot.com/2012/04/datetime-default-now-finally-available.html
MySQL (before version 5.6.5) does not allow functions to be used for default DateTime values. TIMESTAMP is not suitable due to its odd behavior and is not recommended for use as input data. (See MySQL Data Type Defaults.)
That said, you can accomplish this by creating a Trigger.
I have a table with a DateCreated field of type DateTime. I created a trigger on that table "Before Insert" and "SET NEW.DateCreated=NOW()" and it works great.
For me the trigger approach has worked the best, but I found a snag with the approach. Consider the basic trigger to set a date field to the current time on insert:
CREATE TRIGGER myTable_OnInsert BEFORE INSERT ON `tblMyTable`
FOR EACH ROW SET NEW.dateAdded = NOW();
This is usually great, but say you want to set the field manually via INSERT statement, like so:
INSERT INTO tblMyTable(name, dateAdded) VALUES('Alice', '2010-01-03 04:30:43');
What happens is that the trigger immediately overwrites your provided value for the field, and so the only way to set a non-current time is a follow up UPDATE statement--yuck! To override this behavior when a value is provided, try this slightly modified trigger with the IFNULL operator:
CREATE TRIGGER myTable_OnInsert BEFORE INSERT ON `tblMyTable`
FOR EACH ROW SET NEW.dateAdded = IFNULL(NEW.dateAdded, NOW());
This gives the best of both worlds: you can provide a value for your date column and it will take, and otherwise it'll default to the current time. It's still ghetto relative to something clean like DEFAULT GETDATE() in the table definition, but we're getting closer!
I was able to solve this using this alter statement on my table that had two datetime fields.
ALTER TABLE `test_table`
CHANGE COLUMN `created_dt` `created_dt` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
CHANGE COLUMN `updated_dt` `updated_dt` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
This works as you would expect the now() function to work. Inserting nulls or ignoring the created_dt and updated_dt fields results in a perfect timestamp value in both fields. Any update to the row changes the updated_dt. If you insert records via the MySQL query browser you needed one more step, a trigger to handle the created_dt with a new timestamp.
CREATE TRIGGER trig_test_table_insert BEFORE INSERT ON `test_table`
FOR EACH ROW SET NEW.created_dt = NOW();
The trigger can be whatever you want I just like the naming convention [trig]_[my_table_name]_[insert]
You can use triggers to do this type of stuff.
CREATE TABLE `MyTable` (
`MyTable_ID` int UNSIGNED NOT NULL AUTO_INCREMENT ,
`MyData` varchar(10) NOT NULL ,
`CreationDate` datetime NULL ,
`UpdateDate` datetime NULL ,
PRIMARY KEY (`MyTable_ID`)
)
;
CREATE TRIGGER `MyTable_INSERT` BEFORE INSERT ON `MyTable`
FOR EACH ROW BEGIN
-- Set the creation date
SET new.CreationDate = now();
-- Set the udpate date
Set new.UpdateDate = now();
END;
CREATE TRIGGER `MyTable_UPDATE` BEFORE UPDATE ON `MyTable`
FOR EACH ROW BEGIN
-- Set the udpate date
Set new.UpdateDate = now();
END;
For all those who lost heart trying to set a default DATETIME value in MySQL, I know exactly how you feel/felt. So here is is:
ALTER TABLE `table_name` CHANGE `column_name` DATETIME NOT NULL DEFAULT 0
Carefully observe that I haven't added single quotes/double quotes around the 0
I'm literally jumping after solving this one :D
If you have already created the table then you can use
To change default value to current date time
ALTER TABLE <TABLE_NAME>
CHANGE COLUMN <COLUMN_NAME> <COLUMN_NAME> DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;
To change default value to '2015-05-11 13:01:01'
ALTER TABLE <TABLE_NAME>
CHANGE COLUMN <COLUMN_NAME> <COLUMN_NAME> DATETIME NOT NULL DEFAULT '2015-05-11 13:01:01';
MySQL 5.6 has fixed this problem.
ALTER TABLE mytable CHANGE mydate datetime NOT NULL DEFAULT 'CURRENT_TIMESTAMP'
this is indeed terrible news.here is a long pending bug/feature request for this. that discussion also talks about the limitations of timestamp data type.
I am seriously wondering what is the issue with getting this thing implemented.
You can use now() to set the value of a datetime column, but keep in mind that you can't use that as a default value.
I'm running MySql Server 5.7.11 and this sentence:
ALTER TABLE table_name CHANGE date_column datetime NOT NULL DEFAULT '0000-00-00 00:00:00'
is not working. But the following:
ALTER TABLE table_name CHANGE date_column datetime NOT NULL DEFAULT '1000-01-01 00:00:00'
just works.
As a sidenote, it is mentioned in the mysql docs:
The DATE type is used for values with a date part but no time part. MySQL retrieves and displays DATE values in 'YYYY-MM-DD' format. The supported range is '1000-01-01' to '9999-12-31'.
even if they also say:
Invalid DATE, DATETIME, or TIMESTAMP values are converted to the “zero” value of the appropriate type ('0000-00-00' or '0000-00-00 00:00:00').
For all who use the TIMESTAMP column as a solution i want to second the following limitation from the manual:
http://dev.mysql.com/doc/refman/5.0/en/datetime.html
"The TIMESTAMP data type has a range of '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC. It has varying properties, depending on the MySQL version and the SQL mode the server is running in. These properties are described later in this section. "
So this will obviously break your software in about 28 years.
I believe the only solution on the database side is to use triggers like mentioned in other answers.
Working fine with MySQL 8.x
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`dateCreated` datetime DEFAULT CURRENT_TIMESTAMP,
`dateUpdated` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `mobile_UNIQUE` (`mobile`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
While defining multi-line triggers one has to change the delimiter as semicolon will be taken by MySQL compiler as end of trigger and generate error.
e.g.
DELIMITER //
CREATE TRIGGER `MyTable_UPDATE` BEFORE UPDATE ON `MyTable`
FOR EACH ROW BEGIN
-- Set the udpate date
Set new.UpdateDate = now();
END//
DELIMITER ;
Here is how to do it on MySQL 5.1:
ALTER TABLE `table_name` CHANGE `column_name` `column_name`
TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
I have no clue why you have to enter the column name twice.
While you can't do this with DATETIME in the default definition, you can simply incorporate a select statement in your insert statement like this:
INSERT INTO Yourtable (Field1, YourDateField) VALUES('val1', (select now()))
Note the lack of quotes around the table.
For MySQL 5.5
If you are trying to set default value as NOW(), I don't think MySQL supports that. In MySQL, you cannot use a function or an expression as the default value for any type of column, except for the TIMESTAMP data type column, for which you can specify the CURRENT_TIMESTAMP as the default.
I think it simple in mysql since mysql the inbuilt function called now() which gives current time(time of that insert).
So your query should look like similarly
CREATE TABLE defaultforTime(
`creation_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
`modification_time` DATETIME default now()
);
Thank you.
If you set ON UPDATE CURRENT_TIMESTAMP it will take current time when row data update in table.
CREATE TABLE bar(
`create_time` TIMESTAMP CURRENT_TIMESTAMP,
`update_time` TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
CREATE TABLE `testtable` (
`id` INT(10) NULL DEFAULT NULL,
`colname` DATETIME NULL DEFAULT '1999-12-12 12:12:12'
)
In the above query to create 'testtable', i used '1999-12-12 12:12:12' as default value for DATETIME column colname
Use the following code
DELIMITER $$
CREATE TRIGGER bu_table1_each BEFORE UPDATE ON table1 FOR EACH ROW
BEGIN
SET new.datefield = NOW();
END $$
DELIMITER ;
If you are trying to set default value as NOW(),MySQL supports that you have to change the type of that column TIMESTAMP instead of DATETIME. TIMESTAMP have current date and time as default..i think it will resolved your problem..
Take for instance If I had a table named 'site' with a created_at and an update_at column that were both DATETIME and need the default value of now, I could execute the following sql to achieve this.
ALTER TABLE `site` CHANGE `created_at` `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
ALTER TABLE `site` CHANGE `created_at` `created_at` DATETIME NULL DEFAULT NULL;
ALTER TABLE `site` CHANGE `updated_at` `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
ALTER TABLE `site` CHANGE `updated_at` `updated_at` DATETIME NULL DEFAULT NULL;
The sequence of statements is important because a table can not have two columns of type TIMESTAMP with default values of CUREENT TIMESTAMP
This is my trigger example:
/************ ROLE ************/
drop table if exists `role`;
create table `role` (
`id_role` bigint(20) unsigned not null auto_increment,
`date_created` datetime,
`date_deleted` datetime,
`name` varchar(35) not null,
`description` text,
primary key (`id_role`)
) comment='';
drop trigger if exists `role_date_created`;
create trigger `role_date_created` before insert
on `role`
for each row
set new.`date_created` = now();
You can resolve the default timestamp. First consider which character set you are using for example if u taken utf8 this character set support all languages and if u taken laten1 this character set support only for English. Next setp if you are working under any project you should know client time zone and select you are client zone. This step are mandatory.