MySQL:INSERT错误“不能为NULL” - DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP

时间:2017-03-05 21:40:03

标签: mysql sql datetime activerecord

事实上有很多类似的问题,我无法解决这个问题。 我正在使用codeigniter框架。当我通过传递一个php对象来调用ActiveRecord的insert方法时,它会通过其值或null发送所有属性。它会导致cannot be null.错误。

表格结构:

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;

我试过查询:

INSERT INTO `scheduledTasks` (`id`, `type`, `createTime`, `executionTime`, `ownerUserId`, `detail`, `isExecuted`)
VALUES (NULL, 'QuoteRequest', NULL, NULL, '926', NULL, NULL)

Mysql版本:

+-------------------------+
| VERSION()               |
+-------------------------+
| 5.7.17-0ubuntu0.16.04.1 |
+-------------------------+

我有

explicit_defaults_for_timestamp | OFF

和sql模式是

+-------------------------------------------------------------------------------------------------------------------------------------------+
| @@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 |
+-------------------------------------------------------------------------------------------------------------------------------------------+

1 个答案:

答案 0 :(得分:2)

讨论

MySQL 5.7 manual表示......

  

此外,您可以将任何 TIMESTAMP 列初始化或更新到   通过为其指定 NULL 值的当前日期和时间,除非它已被   使用NULL属性定义以允许NULL值。

本手册并未说明您可以对DATETIME字段执行此操作。最好的办法是在INSERTcreateTime字段的executionTime查询中不提供任何值。这应该给你DEFAULT_TIMESTAMP。如果失败了,我试过了。

INSERT INTO `scheduledTasks` (`id`, `type`, `createTime`, `executionTime`, `ownerUserId`, `detail`, `isExecuted`)
VALUES (NULL, 'QuoteRequest', , , '926', NULL, NULL)

另外,请注意MySQL default values,即使您的DATETIME确实有明确的DEFAULT条款。

  

要将数据输入到无显式的NOT NULL DEFAULT   如果INSERT或REPLACE语句包含没有的值,则为子句   或UPDATE语句将列设置为NULL,MySQL处理   根据当时生效的 SQL模式 的列:

     

如果 启用了严格的SQL模式 ,则会在事务表中发生错误并回滚该语句。对于非交易表,   发生错误,但如果第二行或后续行发生这种情况   多行语句,前面的行将是   插入

     

如果未启用 严格模式 ,MySQL会将列设置为列的 隐式默认值 数据类型。

最后,关于MySQL手册中的strict mode

  

对于STRICT_TRANS_TABLES,MySQL将无效值转换为   列的最接近有效值,并插入调整后的值。如果   如果缺少一个值,MySQL会为其插入隐式默认值   列数据类型。在任何一种情况下,MySQL都会生成警告   而不是错误并继续处理该语句。含蓄   第12.7节“数据类型默认值”中描述了默认值。

结论

总之,如果您处于严格模式(您是STRICT_TRANS_TABLES)并且DATETIME列设置为NOT NULL DEFAULT CURRENT_TIMESTAMP,那么您提供在NULL期间INSERT值,然后您得到“不能为空”错误,...下次不会向{{1}提供值}字段。

如果您的框架无法设置为在DATETIME期间省略值,并且更改SQL模式不起作用,则更改要使用的表(gasp)INSERT可能是您使用{的唯一选项{1}}在严格模式下显示TIMESTAMP