OPENJSON和增量值

1szpjjfi  于 2023-06-07  发布在  其他
关注(0)|答案(2)|浏览(193)

我正在尝试解析以下JSON文档:

DECLARE @doc nvarchar(max) = '
{
    "0": {
        "start_time": "1685959230501",
        "timestamp": "10:00:30",
        "running_time": "1.2s",
    },
    "1": {
        "start_time": "1685959230502",
        "timestamp": "10:00:30",
        "running_time": "1.2s",
    },
    "2": {
        "start_time": "1685959230886",
        "timestamp": "10:00:30",
        "running_time": "889.3ms",
    },
    "3": {
        "start_time": "1685959230887",
        "timestamp": "10:00:30",
        "running_time": "883.9ms",
    }"'

SELECT  *
FROM    OPENJSON(@doc, '$.sql:identity()')
WITH    (
        start_time datetime2(3) N'$.start_time'
        , [timestamp] varchar(128) N'$.timestamp'
        , running_time varchar(128) N'$.running_time'
    ) AS i

但是,它会引发以下异常:
消息13607,级别16,状态4,第24行JSON路径格式不正确。在位置5处发现意外字符“:”。
我尝试了几种使用OPENJSON函数的第二个参数的方法,但没有一种有效。有人有主意吗?

shyt4zoc

shyt4zoc1#

在修复了无效的JSON之后,看起来您需要这样做

SELECT
  j1.[key],
  j2.*
FROM OPENJSON(@doc) j1
CROSS APPLY OPENJSON(j1.value)
  WITH (
        start_time bigint
        , [timestamp] time
        , running_time varchar(128)
  ) AS j2;

使用不带模式的OPENJSON获得一系列key, value对,然后再次使用带模式的APPLY OPENJSON将每个对象分解为属性。
还要注意对数据类型的更改。
db<>fiddle

4xy9mtcn

4xy9mtcn2#

您的JSON无效,这是一个问题。对于初学者来说,在每个内部数组的最后一个键/值对后面都有一个逗号;例如"running_time": "1.2s",}。在JSON的末尾还有一个杂散的双引号("),并且没有关闭外部对象。
为了回答这个问题,我将“假设”您有有效的JSON。如果没有,那么需要修复创建上面JSON的进程;它是有缺陷的,并且创建了损坏的JSON,这意味着SQL Server * 无法 * 使用它。
这需要对您想要的结果进行猜测,但假设您希望每个对象有一行,其中一列包含该对象名称的值。
一种方法是使用2个对OPENJSON的调用;第一个将“identity”值放入key列,将内部对象放入另一列。然后,您可以使用OPENJSON调用另一个内部对象。结果如下:

SELECT d.[key],
       v.start_time,
       v.timestamp,
       v.running_time
FROM OPENJSON(@doc) d
     CROSS APPLY OPENJSON(d.[value])
     WITH (start_time bigint,
           timestamp time(0),
           running_time varchar(10)) v;

这将产生以下结果(使用有效的JSON):
| 键|开始时间|时间戳|运行时间|
| - -----|- -----|- -----|- -----|
| 0|电话:1685959230501| 10:00:30| 1.2s |
| 1| 1685959230502| 10:00:30| 1.2s |
| 2|电话:1685959230886| 10:00:30| 889.3ms |
| 3| 1685959230887| 10:00:30| 883.9ms |
如果需要列start_time为实际的日期和时间数据类型(datetime2(0)?)有大量的重复,如:

相关问题