OPENJSON和增量值

huangapple go评论109阅读模式
英文:

OPENJSON and incremental value

问题

我正在尝试解析以下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

然而,它引发了以下异常:

Msg 13607, Level 16, State 4, Line 24
JSON path is not properly formatted. Unexpected character ':' is found at position 5.

我尝试了多种使用OPENJSON函数的第二个参数的方法,但都没有成功。有人有什么想法吗?

英文:

I'm trying to parse the following JSON document :

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

However it raises the following exception :

> Msg 13607, Level 16, State 4, Line 24
> JSON path is not properly formatted. Unexpected character ':' is found at position 5.

I tried several ways using the second parameter of the OPENJSON function, but none has been working.
Does someone have an idea ?

答案1

得分: 1

在修复您的无效JSON后,看起来您想要以下T-SQL查询:

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

英文:

After fixing up your invalid JSON, it looks like you want this


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;

Use OPENJSON without a schema to get a series of key, value pairs, then APPLY OPENJSON again with a schema to break out each object into properties.

Note also the changes to the data types.

db<>fiddle

答案2

得分: 1

你的JSON不是有效的,这是一个问题。首先,在每个内部数组的最后一个键/值对之后,你有一个尾随逗号,例如 &quot;running_time&quot;: &quot;1.2s&quot;,}。此外,你的JSON末尾有一个多余的双引号(&quot;),并且你没有关闭外部对象。

出于这个答案的目的,我将“假设”你有有效的JSON。如果不是有效的JSON,请修复创建上述JSON的过程;它存在缺陷,创建了损坏的JSON,这意味着SQL Server 无法 使用它。

这个答案的目的是翻译上述内容,不包含其他内容。

英文:

Your JSON isn't valid, which is a problem. For starters, you have a trailing comma after the last key/value pair in each of your inner arrays; for example &quot;running_time&quot;: &quot;1.2s&quot;,}. You also have a stray double quote (&quot;) at the end of your JSON and you don't close the outer object.

For the purposes of this answer, I'm going to "assume" you have valid JSON. If you don't, then you need to fix whatever process is creating the above JSON; it is flawed and creating broken JSON meaning that SQL Server cannot consume it.


This takes a guess of the results you want, but presumable you want one row per object, with a column that includes the value of the name of that object.

One method would be to use 2 calls to OPENJSON; the first puts the "identity" value into a key column and the inner object into another column. Then you can consume that inner object with another call with OPENJSON. This results in the following:

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;

This produces the following results (with valid JSON):

key start_time timestamp running_time
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

If you need the column start_time to be an actual date and time data type (datetime2(0)?) there are plenty of duplicates, such as:

huangapple
  • 本文由 发表于 2023年6月5日 23:50:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76408092.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定