当前日期/CURDATE()不能作为默认的日期值工作

80

这里有一个非常直接的问题,我认为这个应该可以工作,但事实并非如此。为什么不行呢?

CREATE TABLE INVOICE(
   INVOICEDATE DATE NOT NULL DEFAULT CURRENT_DATE
)

10
这个问题已经过时了。更新的版本允许这样做。请参考我的回答,了解版本号及其发布日期。换句话说,更新可能是你的答案。 - Rick James
截至2021年10月,第五个答案是正确的。 - t1f
10个回答

88

[编辑] 截至MySQL 8.0.13版本,已支持。请参见下方this answer

它不起作用是因为不支持

DEFAULT子句指定列的默认值。除一种情况外,默认值必须是常量;不能是函数或表达式。这意味着,例如,您不能将日期列的默认值设置为诸如NOW()CURRENT_DATE之类的函数的值。例外是您可以将CURRENT_TIMESTAMP指定为TIMESTAMP列的默认值

http://dev.mysql.com/doc/refman/5.5/en/create-table.html


@inControl:是的,使用DATE_FORMAT - zerkms
38
现在是2016年,令人感到荒谬的是,这个事实仍然存在。我认为不断提供同义词的整个原因是允许它们出现在非常量表达式被禁止的地方。 - Dan Lugg
12
我已将其解决,通过迁移到postgresql :-) - zerkms
1
请注意,@NorthbornDesign的答案是正确的 :) - Yehosef
对于一个 change_date 列(更新和删除):CREATE TABLE t1 ( ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); https://dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html - Ralf Hundewadt
1
截至2021年10月,第五个答案是正确的。它有效! - t1f

54
根据此文档,从MySQL 8.0.13开始,您将能够指定:
CREATE TABLE INVOICE(
    INVOICEDATE DATE DEFAULT (CURRENT_DATE)
)

MySQL 8.0.13于2018年10月发布为正式版本。发布信息位于此处


3
在我这里是可以工作的,谢谢。(先看一下 MySQL 的版本)。 - Mylon
1
需要注意的重要事项是,表达式必须在括号内。没有括号,默认情况下必须是字面量(除了 CURRENT_TIMESTAMP())。 - Barmar

31

MySQL 8 开始,可以将以下设置为 DATE 列:

MySQL Workbench 中,在列旁边的 Default 字段中写入:(curdate())

如果只写 curdate() ,会失败。你需要在开头和结尾加上额外的 ()


3
正确的是,需要注意额外的括号,非常感谢。 - Muhammad Faizan Khatri
1
这在MySQL 8.0.21中有效。语法有点奇怪。谢谢! - The Onin
1
@NinoŠkopac 确实。那些奇怪的额外括号让我花了一整天的时间来搜索。他们的官方文档在这个方面并不清楚。看来这就是小事情 ^_^。很高兴它对你有用。 - t1f
1
现在应该将其标记为正确答案。 - Ethan Allen
1
非常感谢您的解决方案!! - Alexa
显示剩余5条评论

27

将您的日期列声明为NOT NULL,但不带默认值。然后添加此触发器:

USE `ddb`;
DELIMITER $$
CREATE TRIGGER `default_date` BEFORE INSERT ON `dtable` FOR EACH ROW
if ( isnull(new.query_date) ) then
 set new.query_date=curdate();
end if;
$$
delimiter ;

我不得不将字段设置为“NULL”才能使其正常工作,否则它会插入“0000-00-00”。MySQL v5.6.12。 - lolbas

16
create table the_easy_way(
  capture_ts DATETIME DEFAULT CURRENT_TIMESTAMP,
  capture_dt DATE AS (DATE(capture_ts))
)

(MySQL 5.7)


最近版本的MySQL似乎需要在(CURRENT_TIMESTAMP)周围加上额外的括号。 - Sushil

8

我目前使用的是最新版本的MySQL:8.0.20。

因此,我的表名为visit,列名为curdate。

alter table visit modify curdate date not null default (current_date);

这将使用默认日期值而不带时间戳进行编写。

1
我已经尝试过这个方法并且成功了。我认为这应该是被接受的答案。 - Dika
同意。这是最佳答案。 - Kristoffer Tølbøll

4

----- 2016-07-04 MariaDB 10.2.1 -- 发布说明 -- -----

支持 带有表达式的DEFAULT (MDEV-10134)。

----- 2018-10-22 8.0.13 一般可用性 -- -- -----

MySQL现在支持在数据类型规范中使用表达式作为默认值。这包括将表达式用作BLOB, TEXT, GEOMETRY和JSON数据类型的默认值,而这些数据类型以前根本不能被分配默认值。有关详细信息,请参见数据类型默认值


3
正如其他答案所指出的那样,您不能将动态函数用作默认值。您可以使用带有CURRENT_TIMESTAMP属性的TIMESTAMP,但这并非总是可能的,例如如果您想保留创建更新时间戳,并且您需要第二个允许的TIMESTAMP列。

在这种情况下,请改用触发器


1
自动时间戳数量的限制在 MySQL 5.6 中被取消了。 - Michael - sqlbot
谢谢您的补充,我之前不知道这个信息 - 但是最好还是记在心里,因为大多数网络托管仍然使用5.1或5.5版本。 - Niels Keurentjes
1
MariaDB 10.2.1 允许使用 DEFAULT(expression)。请参见创建表 - Rick James
你应该在 @RickJames 处添加一个答案。 - Peter Chaula

3

我也曾经有同样的问题,但是这个方法对我很有效!我来更新一下,或许以后会对别人有帮助!

MariaDB [niffdb]> desc invoice;
+---------+--------+------+-----+---------+----------------+
| Field   | Type   | Null | Key | Default | Extra          |
+---------+--------+------+-----+---------+----------------+
| inv_id  | int(4) | NO   | PRI | NULL    | auto_increment |
| cust_id | int(4) | NO   | MUL | NULL    |                |
| inv_dt  | date   | NO   |     | NULL    |                |
| smen_id | int(4) | NO   | MUL | NULL    |                |
+---------+--------+------+-----+---------+----------------+
4 rows in set (0.003 sec)

MariaDB [niffdb]> ALTER TABLE invoice MODIFY inv_dt DATE NOT NULL DEFAULT (CURRENT_DATE);
Query OK, 0 rows affected (0.003 sec)
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [niffdb]> desc invoice;
+---------+--------+------+-----+-----------+----------------+
| Field   | Type   | Null | Key | Default   | Extra          |
+---------+--------+------+-----+-----------+----------------+
| inv_id  | int(4) | NO   | PRI | NULL      | auto_increment |
| cust_id | int(4) | NO   | MUL | NULL      |                |
| inv_dt  | date   | NO   |     | curdate() |                |
| smen_id | int(4) | NO   | MUL | NULL      |                |
+---------+--------+------+-----+-----------+----------------+
4 rows in set (0.002 sec)

MariaDB [niffdb]> SELECT VERSION();
+---------------------------+
| VERSION()                 |
+---------------------------+
| 10.3.18-MariaDB-0+deb10u1 |
+---------------------------+
1 row in set (0.010 sec)

MariaDB [niffdb]>

DEFAULT LAST_DAY(CURDATE())对我来说可以工作,甚至没有括号。但是一些phpmyadmin功能可能会触发错误。 - Hebe

1
创建表时,您需要使用CURRENT_DATE()函数作为默认值。请看下面我刚测试过的例子。
CREATE TABLE SALES_DATA (
    SALES_ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
    SALES_GIRL_ID INT UNSIGNED NOT NULL,
    SALES_DATE DATE NOT NULL DEFAULT (CURRENT_DATE()),
    TOTAL_SALES FLOAT(6, 2),
    PRIMARY KEY (SALES_ID),
    FOREIGN KEY (SALES_GIRL_ID) REFERENCES SALES_GIRLS(ID)
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接