鉴于此表结构:
CREATE TABLE t3 (
`id` bigint NOT NULL AUTO_INCREMENT,
`abc` bigint NOT NULL,
`ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`createdday` int GENERATED ALWAYS AS (cast(`ts` as date)) STORED NOT NULL,
PRIMARY KEY (`id`)
);
在一个 MySQL 版本 8.0.25 实例中,当我们执行
insert into t3 (abc) values (2);
时,它可以成功写入该行并且 createdday
可以得到正确的值,但在另一个具有相同版本的 MySQL 实例中,它显示错误 ERROR 1048 (23000): Column 'createdday' cannot be null
。
在MySQL bug列表中,有一个关于这个的问题https://bugs.mysql.com/bug.php?id=94550,但里面没有更新。
我检查了配置变量,它们是相同的。尤其是
explicit_defaults_for_timestamp
是OFF
。有人知道为什么一个MySQL实例可以正确保存它而另一个却不能?以及如何解决这个问题?
我对MySQL版本做了一些测试
8.0.39-0ubuntu0.22.04.1
。
表格说明
CREATE TABLE `t3` (
`id` bigint NOT NULL AUTO_INCREMENT,
`abc` bigint NOT NULL,
`ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`createdday` int GENERATED ALWAYS AS (cast(`ts` as date)) STORED NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB
mysql> insert into t3(abc) values(1);
ERROR 1048 (23000): Column 'createdday' cannot be null
将
explicit_defaults_for_timestamp
会话和全局设置为 OFF 和 ON 时,会发生相同的错误,但如果我使用以下查询
mysql> insert into t3(abc,ts) values(1,current_date());
Query OK, 1 row affected (0.02 sec)
mysql> select * from t3;
+----+-----+---------------------+------------+
| id | abc | ts | createdday |
+----+-----+---------------------+------------+
| 1 | 1 | 2024-09-19 00:00:00 | 20240919 |
+----+-----+---------------------+------------+
1 row in set (0.00 sec)
效果很好。
来自创建表和生成的列
如果生成的列使用 TIMESTAMP 数据类型,则忽略
explicit_defaults_for_timestamp
的设置。在这种情况下,如果禁用此变量,则 NULL 不会转换为 CURRENT_TIMESTAMP。如果该列也声明为 NOT NULL,则尝试插入 NULL 会被明确拒绝,并显示 ER_BAD_NULL_ERROR