在 SQL Server 中读取 JSON 数据时无法从字符串转换为日期时间

Posted

技术标签:

【中文标题】在 SQL Server 中读取 JSON 数据时无法从字符串转换为日期时间【英文标题】:Cannot Convert from String to Datetime while reading JSON data in SQL Server 【发布时间】:2021-12-28 09:32:36 【问题描述】:
DECLARE @JSON AS varchar(MAX)

SET @JSON = '[
 
"UserId": "XYZ12345",
"LoginTime": "2021-12-25T07:48:59Z"
 ,
 
"UserId": "XYZ67890",
"LoginTime": "2021-12-24T07:48:59Z"
    
  ]'

SELECT * 
FROM OPENJSON(@json) 
WITH ( 
         UserId nvarchar(MAX) '$.UserId', 
         LoginTime datetime '$.LoginTime'           
     ) 
ORDER BY UserId ASC

但是,我得到一个错误

从字符串转换日期和/或时间时转换失败

【问题讨论】:

Cannot reproduce。语言设置也不应该影响这一点。您可以尝试DATETIMEOFFSET,因为它明确设计用于处理时区(如果您不需要时区信息,您可以进一步转换它),但如果“修复”它,仍然会有一些奇怪的事情发生。 同意,您使用的格式是明确的,这意味着您实际上拥有的日期/时间值是完全无效的。如2021-02-29T25:00:17Z @Larnu 这将产生不同的错误消息(至少在 2019 年 - The conversion of a nvarchar data type to a datetime data type resulted in an out-of-range value.)但是我同意这很可能是由无效数据引起的 - 但我怀疑它可能更像是打字错误 - 某人使用O 而不是0 或类似的东西。 请更新此working DB Fiddle 以重现错误 值得注意的是,如果输入中存在 not Z 的时区,则会发生此确切错误。显然,如果使用 UTC 时区字符串,则仅允许以静默方式转换为 DATETIME;对于其他时区偏移,必须使用 DATETIMEOFFSET。当然,如果已知输入包含时区指示符,则显式使用 DATETIMEOFFSET 是个好主意。 【参考方案1】:

JSON 数据中的一些登录时间可能有时区。

将其转换为 DATETIME 时会引发错误。

但是将它们转换为 DATETIME2 或 DATETIMEOFFSET 就可以了。

那么 DATETIMEOFFSET 可能是更好的选择,因为它会包含时区。

简化测试:

SELECT * 
FROM OPENJSON('["LoginTime": "2021-12-25T07:48:59+01:00"]') 
WITH ( LoginTime datetime '$.LoginTime' ) 
GO
消息 241 级别 16 状态 1 第 1 行 从字符串转换日期和/或时间时转换失败。
SELECT * 
FROM OPENJSON('["LoginTime": "2021-12-25T07:48:59+01:00"]') 
WITH ( LoginTime datetime2 '$.LoginTime' ) 
GO
|登录时间 | | :---------------------------- | | 2021-12-25 07:48:59.0000000 |
SELECT * 
, SWITCHOFFSET(LoginTime, '+00:00') AS LoginTimeZulu
FROM OPENJSON('["LoginTime": "2021-12-25T07:48:59+03:00"]') 
WITH ( LoginTime datetimeoffset '$.LoginTime' ) 
GO
登录时间 |登录时间Zulu :--------------------------------- | :-------------------------------- 2021-12-25 07:48:59.0000000 +03:00 | 2021-12-25 04:48:59.0000000 +00:00

db小提琴here

【讨论】:

哎哟。它允许在丢弃 TZ 信息的同时静默转换为DATETIME2,这有点不妥,因为除非所有偏移量都恰好相同,否则这没有希望是正确的。这使得在涉及时区时使用DATETIMEOFFSET 变得更加重要(如果需要,以后可以转换)。 @JeroenMostert 情况更糟。 DATETIMEOFFSET 到 DATETIME2 或 DATETIME 的 CAST 不会根据时区更改时间。

以上是关于在 SQL Server 中读取 JSON 数据时无法从字符串转换为日期时间的主要内容,如果未能解决你的问题,请参考以下文章

在SQL Server中读和写JSON

SQL Server 中的 JSON 数据

SQL Server OPENJSON 读取嵌套的 json

我已经安装了json-server 但是就是读不到配置文件当前目录下的db.json

如何使用 openjson 读取存储在 SQL Server 中的 Json 列下方?

从 sql server 读取数据时检测到自引用循环