MySQL插入日期时间:使用ISO::8601格式安全吗?

MySQL插入日期时间:使用ISO::8601格式安全吗?,mysql,datetime,iso8601,Mysql,Datetime,Iso8601,在我们的项目中,我们使用Zend Framework Model generator,它生成如下内容来设置存储在DB(MySQL)中作为日期时间字段的属性: public function setObjectDatetime($data) { if (! $data instanceof Zend_Date) { ... some conversion code ... } $this->objectDatetime = $data->toString(Zend_Date::

在我们的项目中,我们使用Zend Framework Model generator,它生成如下内容来设置存储在DB(MySQL)中作为日期时间字段的属性:

public function setObjectDatetime($data) {
  if (! $data instanceof Zend_Date) { ... some conversion code ... }
  $this->objectDatetime = $data->toString(Zend_Date::ISO_8601);
}
因此ISO::8601格式的字符串(“例如,2012-06-15T18:33:00+03:00”)实际上是作为属性存储的

当我们尝试
保存该模型,并将该字符串传递给MySQL(版本5.5.16)时,问题就出现了:它会发出警告,但仍然会插入/更新相应的行并得到正确的结果。很容易检查问题是否是由MySQL引起的,而不是某些驱动程序的行为:只需发出如下查询

UPDATE table_name SET datetime_field = '2012-06-15T18:33:00+03:00' WHERE id = 1;
。。。结果将
1行受影响,1条警告
,带有

1264 |第1行“dt”列的值超出范围

警告(通过显示警告来显示)

据我所知,phpMyAdmin根本没有显示任何警告;所有服务器端代码都将此查询作为一个可靠的查询进行处理。)


所以问题是:我们真的应该将我们存储在模型中的内容重新格式化为另一种字符串格式(例如,YY-MM-dd HH:MM:ss),还是只是MySQL的一些奇怪行为迟早会被修复?

据我所知,没有办法存储时间偏移信息(ISO 8601字符串末尾的+03:00)在MySQL的日期或时间类型中,您可以自行找到解决方案

一种可能的方法是拆分ISO8601字符串,并将偏移量存储在char(5)列中,尽管不可否认,这会使处理起来有点困难。我想您可以将偏移量存储在时间列中,这可能会使日期/时间操作更容易一些

编辑

我刚刚偶然发现了MySQL文档,这可能会有所帮助。

这个问题的简短答案似乎是“不,它不安全”——这个结论是在MySQL shell的一系列实验之后得出的。不过,我还是希望能有一个更“理论化”的答案

显然,MySQL引擎(默认情况下)在接受Datetime文本方面相当自由,即使
sql\u模式
设置为STRICT\u ALL\u表:不仅接受各种分隔符,它们也可能不同:

插入t(dt)值('2012-01,03.04:05@06'); -- 查询确定,1行受影响

此外,如果字符串太短,将用零填充。。。但可能会有惊喜:

插入t(dt)值('2012011');--2020-12-01 01:00:00是插入的内容

可悲的是,字符串太长(当最后一个可解析数字后面跟的不是空白)将在严格模式下被视为无效值:

mysql> INSERT INTO t(dt) VALUES('2012-06-27T05:25Z');
ERROR 1292 (22007): Incorrect datetime value: '2012-06-27T05:25Z' for column 'dt' at row 1
mysql> INSERT INTO t(dt) VALUES('2012-06-27T05:25');
Query OK, 1 row affected (0.10 sec)
在传统模式下,解析更加轻松,但并不更加精确;此外,在严格模式下被认为不正确的字符串将发出某种“无声警告”,尽管操作会成功:

mysql> INSERT INTO t(dt) VALUES('2012-06-27T05:25Z');
Query OK, 1 row affected, 1 warning (0.10 sec)

mysql> SHOW WARNINGS;
+---------+------+---------------------------------------------+
| Warning | 1264 | Out of range value for column 'dt' at row 1 |
+---------+------+---------------------------------------------+

mysql> SELECT dt FROM t;
+---------------------+
| dt                  |
+---------------------+
| 2012-06-27 05:25:00 |
+---------------------+

底线是我们必须重写一些与DAL相关的代码,以便日期(和日期时间)总是以“规范化”的形式发送到DB。我想知道为什么我们必须这么做,而不是Zend_Db开发人员。但我想那是另一回事了。)

默认情况下,MySQL对datetime使用ISO9075格式

第一个和第二个参数的可能值会产生几个可能的格式字符串(有关所使用的说明符,请参阅DATE_format()函数描述中的表格)。ISO格式指的是ISO 9075,而不是ISO 8601


我明白你的意思,但问题更多的是格式本身的有效性。)实际上,在我们的例子中,Zend_Date将所有日期时间转换为GMT时间,因此这些字符串中的时区偏移量始终为+00:00。无论如何,谢谢你的回答。)看起来MySQL根本没有解析时区偏移量:至少时间戳字段使用了与我使用的“+XX:00”相同的数据进行了更新。悲哀。哦,好吧,我的误解-我认为时区信息很重要/必要。如果你跨时区工作,这是必要的。PS MySql默认情况下,当显示无法转换的数据时,Google MySql会对细节进行最佳猜测,这说明了插入时区信息的可能方式。但是我认为用服务器端转换日期时间(并且考虑所有日期时间仅存储为GMT)是一种更好的方法……尤其是在mysql 5.7中,这样做会出错。“Y-m-d H:i:s”