我遇到了一个问题,试图在我一生中都找不到的表中插入日期。假设我这样做:
select "2018-11-40" from dual where dayname("2018-02-31") is not null;
我正确地获得了0行,因为11月40日不是有效的一天。
但是如果我有一个带有日期字段EVENT_DATE
的表MY_TABLE,请执行以下操作:
insert into MY_TABLE (EVENT_DATE)
select "2018-11-40" from dual where dayname("2018-11-40") is not null;
出现以下错误:错误的日期时间值:'2018-11-40',而不是运行时没有错误并且影响了0行。
(dayname("2018-11-40") is not null)
绝对应在插入之前解析为false ...,如果我这样做:
insert into MY_TABLE (EVENT_DATE)
select "2018-11-40" from dual where 1=2;
一切正常(没有错误。受影响的0行)。
那有什么用呢?这是在MySQL 5.7.21上
答案 0 :(得分:2)
在mysql 5.7中,您对select "2018-11-40" from dual where dayname("2018-02-31") is not null;
的初始查询实际上正在生成警告。
通过直接使用show warnings;
您应该会看到类似的内容:
+---------+------+----------------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------------+
| Warning | 1292 | Incorrect datetime value: '2018-02-31' |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)
如果我对您的理解正确,那么您发现有问题的是您认为行为从测试选择到尝试将选择用作插入内容的输入的行为上的差异。
该问题的答案与您可以配置的various server sql mode settings有关。
您看到的是“严格模式”与默认设置NO_ZERO_DATE的组合。手册说明了有关设置的组合:
如果启用了此模式和严格模式,则除非也给出了IGNORE,否则不允许'0000-00-00'并且插入会产生错误。对于INSERT IGNORE和UPDATE IGNORE,允许使用“ 0000-00-00”,并且插入会产生警告。
您的无效日期将被转换为'00',当您使用SELECT时会触发警告,但是如果您尝试将其与INSERT结合使用,则会引发完全错误。
答案 1 :(得分:1)
在DML语句(INSERT / UPDATE / DELETE)中,1292
是错误。
但是在SELECT
语句中,1292
不是错误。这是一个警告,因此该语句可以继续处理。
Query: select '2018-11-40' + INTERVAL 0 DAY
1 row(s) affected, 1 warning(s)
Warning Code : 1292
Incorrect datetime value: '2018-11-40'
SELECT语句引发警告。 MySQL会报告它,但是您的客户端应用程序会忽略它。
区别在于,在带有警告条件的情况下,语句可以继续处理。在INSERT
语句的上下文中,1292是错误,并且语句处理停止。
(例如,sql_mode
的设置可能会影响MySQL 5.7中的此行为,例如,使SELECT语句抛出错误而不是警告。)
我们可以看到错误1411的相同行为。这是DML中的错误,是SELECT中的警告。
Query: select STR_TO_DATE('2018-11-40','%Y-%m-%d')
1 row(s) affected, 1 warning(s)
Warning Code : 1411
Incorrect datetime value: '2018-11-40' for function str_to_date