将数据从 JSON 插入数据库 table 时避免使用多个 INSERT 语句
Avoid using multiple INSERT statements when inserting data from JSON to database table
我在 SQL 服务器上编写了一个存储过程,它将以下内容作为输入 JSON post:
{"sentiment_results": {"polarity": -0.6, "subjectivity": 0.7, "emotions": {"anger": 0.08296050131320953, "disgust": 0.00219865539111197, "fear": 0.07708118110895157, "joy": 0.757244884967804, "surprise": 0.027166856452822685, "sadness": 0.05334791541099548}}, "sentiment_time": "2020-08-04T16:43:47.141948"}
...并使用以下脚本在数据库 table 中输入数据(post_metric_score table -> 每个数据点一行)
INSERT INTO [STAGING].[post_metric_score]([post_id],[metric_id],[score])
SELECT @post_id, 1, try_convert(decimal(12, 8), [score])
FROM OPENJSON(@postJson, '$.sentiment_results')
WITH ([score] FLOAT '$.polarity')
INSERT INTO [STAGING].[post_metric_score]([post_id],[metric_id],[score])
SELECT @post_id, 2, try_convert(decimal(12, 8), [score])
FROM OPENJSON(@postJson, '$.sentiment_results')
WITH ([score] FLOAT '$.subjectivity')
INSERT INTO [STAGING].[post_metric_score]([post_id],[metric_id],[score])
SELECT @post_id, 3, try_convert(decimal(12, 8), [score])
FROM OPENJSON(@postJson, '$.sentiment_results.emotions')
WITH ([score] FLOAT '$.anger')
INSERT INTO [STAGING].[post_metric_score]([post_id],[metric_id],[score])
SELECT @post_id, 4, try_convert(decimal(12, 8), [score])
FROM OPENJSON(@postJson, '$.sentiment_results.emotions')
WITH ([score] FLOAT '$.disgust')
INSERT INTO [STAGING].[post_metric_score]([post_id],[metric_id],[score])
SELECT @post_id, 5, try_convert(decimal(12, 8), [score])
FROM OPENJSON(@postJson, '$.sentiment_results.emotions')
WITH ([score] FLOAT '$.fear')
INSERT INTO [STAGING].[post_metric_score]([post_id],[metric_id],[score])
SELECT @post_id, 6, try_convert(decimal(12, 8), [score])
FROM OPENJSON(@postJson, '$.sentiment_results.emotions')
WITH ([score] FLOAT '$.joy')
该脚本工作正常,但它使用了很多 CPU,因为每个 JSON post.[=14= 运行 将相同的插入查询插入 6 次]
有没有办法简化上面的脚本,这样就不必多次 运行 插入语句?
您可以打开 JSON 一次,获取您想要的列并使用 apply
取消透视。这是一个包含两列的示例:
INSERT INTO [STAGING].[post_metric_score]([post_id], [metric_id], [score])
SELECT @post_id, v.metric_id, try_convert(decimal(12, 8), v.score)
FROM OPENJSON(@postJson, '$.sentiment_results')
WITH (polarity FLOAT '$.polarity',
subjectivity FLOAT '$.subjectivity'
) as o CROSS APPLY
(VALUES (1, o.polarity), (2, o.subjectivity)
) v(metric_id, score);
所有列:
INSERT INTO [STAGING].[post_metric_score]([post_id], [metric_id], [score])
SELECT @post_id, v.metric_id, try_convert(decimal(12, 8), v.score)
FROM OPENJSON(@postJson, '$.sentiment_results')
WITH (polarity FLOAT '$.polarity',
subjectivity FLOAT '$.subjectivity',
anger FLOAT '$.emotions.anger',
disgust FLOAT '$.emotions.disgust',
fear FLOAT '$.emotions.fear',
joy FLOAT'$.emotions.joy'
) as o CROSS APPLY
(VALUES (1, o.polarity), (2, o.subjectivity), (3, o.anger), (4, o.disgust), (5, o.fear), (6, o.joy)
) v(metric_id, score);
Here 是 SQL fiddle.
另一个选项是使用 JSON_VALUE()
(注意,OPENJSON()
可能比使用 JSON_VALUE()
六次更快):
INSERT INTO [STAGING].[post_metric_score]([post_id], [metric_id], [score])
SELECT @postId, [metric_id], TRY_CONVERT(decimal(12, 8), [score])
FROM (VALUES
(1, JSON_VALUE(@postJson, '$.sentiment_results.polarity')),
(2, JSON_VALUE(@postJson, '$.sentiment_results.subjectivity')),
(3, JSON_VALUE(@postJson, '$.sentiment_results.emotions.anger')),
(4, JSON_VALUE(@postJson, '$.sentiment_results.emotions.disgust')),
(5, JSON_VALUE(@postJson, '$.sentiment_results.emotions.fear')),
(6, JSON_VALUE(@postJson, '$.sentiment_results.emotions.joy'))
) v ([metric_id], [score])
我在 SQL 服务器上编写了一个存储过程,它将以下内容作为输入 JSON post:
{"sentiment_results": {"polarity": -0.6, "subjectivity": 0.7, "emotions": {"anger": 0.08296050131320953, "disgust": 0.00219865539111197, "fear": 0.07708118110895157, "joy": 0.757244884967804, "surprise": 0.027166856452822685, "sadness": 0.05334791541099548}}, "sentiment_time": "2020-08-04T16:43:47.141948"}
...并使用以下脚本在数据库 table 中输入数据(post_metric_score table -> 每个数据点一行)
INSERT INTO [STAGING].[post_metric_score]([post_id],[metric_id],[score])
SELECT @post_id, 1, try_convert(decimal(12, 8), [score])
FROM OPENJSON(@postJson, '$.sentiment_results')
WITH ([score] FLOAT '$.polarity')
INSERT INTO [STAGING].[post_metric_score]([post_id],[metric_id],[score])
SELECT @post_id, 2, try_convert(decimal(12, 8), [score])
FROM OPENJSON(@postJson, '$.sentiment_results')
WITH ([score] FLOAT '$.subjectivity')
INSERT INTO [STAGING].[post_metric_score]([post_id],[metric_id],[score])
SELECT @post_id, 3, try_convert(decimal(12, 8), [score])
FROM OPENJSON(@postJson, '$.sentiment_results.emotions')
WITH ([score] FLOAT '$.anger')
INSERT INTO [STAGING].[post_metric_score]([post_id],[metric_id],[score])
SELECT @post_id, 4, try_convert(decimal(12, 8), [score])
FROM OPENJSON(@postJson, '$.sentiment_results.emotions')
WITH ([score] FLOAT '$.disgust')
INSERT INTO [STAGING].[post_metric_score]([post_id],[metric_id],[score])
SELECT @post_id, 5, try_convert(decimal(12, 8), [score])
FROM OPENJSON(@postJson, '$.sentiment_results.emotions')
WITH ([score] FLOAT '$.fear')
INSERT INTO [STAGING].[post_metric_score]([post_id],[metric_id],[score])
SELECT @post_id, 6, try_convert(decimal(12, 8), [score])
FROM OPENJSON(@postJson, '$.sentiment_results.emotions')
WITH ([score] FLOAT '$.joy')
该脚本工作正常,但它使用了很多 CPU,因为每个 JSON post.[=14= 运行 将相同的插入查询插入 6 次]
有没有办法简化上面的脚本,这样就不必多次 运行 插入语句?
您可以打开 JSON 一次,获取您想要的列并使用 apply
取消透视。这是一个包含两列的示例:
INSERT INTO [STAGING].[post_metric_score]([post_id], [metric_id], [score])
SELECT @post_id, v.metric_id, try_convert(decimal(12, 8), v.score)
FROM OPENJSON(@postJson, '$.sentiment_results')
WITH (polarity FLOAT '$.polarity',
subjectivity FLOAT '$.subjectivity'
) as o CROSS APPLY
(VALUES (1, o.polarity), (2, o.subjectivity)
) v(metric_id, score);
所有列:
INSERT INTO [STAGING].[post_metric_score]([post_id], [metric_id], [score])
SELECT @post_id, v.metric_id, try_convert(decimal(12, 8), v.score)
FROM OPENJSON(@postJson, '$.sentiment_results')
WITH (polarity FLOAT '$.polarity',
subjectivity FLOAT '$.subjectivity',
anger FLOAT '$.emotions.anger',
disgust FLOAT '$.emotions.disgust',
fear FLOAT '$.emotions.fear',
joy FLOAT'$.emotions.joy'
) as o CROSS APPLY
(VALUES (1, o.polarity), (2, o.subjectivity), (3, o.anger), (4, o.disgust), (5, o.fear), (6, o.joy)
) v(metric_id, score);
Here 是 SQL fiddle.
另一个选项是使用 JSON_VALUE()
(注意,OPENJSON()
可能比使用 JSON_VALUE()
六次更快):
INSERT INTO [STAGING].[post_metric_score]([post_id], [metric_id], [score])
SELECT @postId, [metric_id], TRY_CONVERT(decimal(12, 8), [score])
FROM (VALUES
(1, JSON_VALUE(@postJson, '$.sentiment_results.polarity')),
(2, JSON_VALUE(@postJson, '$.sentiment_results.subjectivity')),
(3, JSON_VALUE(@postJson, '$.sentiment_results.emotions.anger')),
(4, JSON_VALUE(@postJson, '$.sentiment_results.emotions.disgust')),
(5, JSON_VALUE(@postJson, '$.sentiment_results.emotions.fear')),
(6, JSON_VALUE(@postJson, '$.sentiment_results.emotions.joy'))
) v ([metric_id], [score])