当前位置: 首页 > 面试题库 >

MySQL插入DATETIME:使用ISO :: 8601格式是否安全?

朱阳曜
2023-03-14
问题内容

在我们的项目中,我们使用Zend Framework
Model生成器,该生成器会生成类似这样的内容,以将存储在DB(MySQL)中的属性设置为DATETIME字段:

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’)实际上是作为属性存储的。

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

UPDATE table_name SET datetime_field = '2012-06-15T18:33:00+03:00' WHERE id = 1;

......其结果将是1 row affected, 1 warning,与

1264 | Out of range value for column 'dt' at row 1

警告(由显示SHOW WARNINGS)。

令我大失所望的是,phpMyAdmin根本不显示任何警告。并且所有服务器端代码都将此查询作为可靠的查询进行处理。)

因此,问题是:我们是否应该将我们存储在模型中的内容重新格式化为另一种字符串格式(例如,’YY-MM-dd
HH:mm:ss’?)还是只是将解决一些奇怪的MySQL行为迟早?


问题答案:

这个问题的简短答案似乎是“不,这并不安全”-这个结论是通过对MySQL Shell进行的一系列实验得出的。不过,仍然会希望有一个更“理论上”的答案。

显然,MySQL引擎(默认情况下)在它作为Datetime文字接受的方面是相当自由的,即使将其sql_mode设置为STRICT_ALL_TABLES:不仅接受各种分隔符,它们也可能有所不同:

INSERT INTO t(dt) VALUES('2012-01,03.04:05@06'); -- Query OK, 1 row affected

此外,如果字符串太短,则会用零填充…,但可能会令人惊讶:

INSERT INTO t(dt) VALUES('2012011'); -- 2020-12-01 01:00:00 is what's inserted

可悲的是,字符串太长(当最后一个可分析的数字后跟空格以外的其他内容时)在严格模式下将被视为无效值:

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相关的代码,以便日期(和日期时间)始终以“规范化”形式发送到数据库。我想知道为什么要做的是我们,而不是Zend_Db开发人员。我想那是另一个故事。)



 类似资料:
  • 问题内容: 我将Spring Framework用于我的服务API和日期时间解析。具体来说,我使用,它使用户可以灵活地仅使用日期,或者同时使用日期和时间,这是必需的。 相信我,我已经看到了所有这些我可以告诉人们的相关问题,例如this和this等等。 以前,我以日期为准,然后在服务层中使用上面提到的joda格式化程序处理日期,但是现在我想在控制器中添加请求验证,这意味着如果请求在语法上不正确,则该

  • 我使用Spring Framework作为我的服务API,使用作为日期时间解析。具体地说,我使用的是,它允许用户灵活地只使用日期,或者同时使用日期和时间,这是一个要求。 我尝试过使用的多种变体,以及在format中指定字符串,但无论如何都没有成功。 我应该做什么来确保我从用户那里获得的日期符合格式?我可以应用多个模式来实现它吗?

  • 问题内容: 我试图以标准时间戳记从数据库中获取日期并将其显示为ISO8601。我无法轻松地在PHP中执行此操作,因此尝试在SELECT语句中进行操作。这是我所拥有的,但是显示错误: 我究竟做错了什么? 问题答案: 本必须在列表:

  • 问题内容: 如果要将结果插入MySQL 类型列中,传递给PHP函数的正确格式是什么? 我一直在尝试,但是每次都只插入“ 0000-00-00 00:00:00”。 问题答案: 问题是您正在使用和,它们是文本表示形式,MySQL希望使用格式的数字表示形式 尝试:使用数字等效项。 编辑:切换到,尽管可能没有影响,但您可能希望使用前导0的24小时格式。

  • 问题内容: 我正在尝试从标准ISO 8601 格式更改为好的MMM d yyyy hh:mm z格式,但是我当前的代码失败。 我正在从api接收时间和日期。 问题答案: A 是“ ISO-8601日历系统中没有时区的日期,例如2007-12-03”,因此那里没有足够的信息。使用代替。 同样,吞噬这样的异常会使得排除故障变得更加困难。当您不打算处理异常时,要么根本不捕获它,要么捕获并重新包装在Run

  • 问题内容: Java 7 通过字符(而不是大写或小写)引入了对ISO 8601格式的支持。在Java 6中支持此类格式需要进行预处理,因此最好的方法就是问题。 此新格式是(大写字母Z)的超集,还有2个其他变体: “分钟”字段是可选的(即有效的是2位数而不是4位数的时区) 冒号(’:’)可用于将两位数字的“小时”字段与两位数字的“分钟”字段分开。 因此,从Java 7文档的 可以看到,以下三种格式现