【问题标题】:Avoid using multiple INSERT statements when inserting data from JSON to database table将数据从 JSON 插入数据库表时避免使用多个 INSERT 语句
【发布时间】:2020-08-05 19:27:42
【问题描述】:

我在 SQL Server 上编写了一个存储过程,将以下 JSON 帖子作为输入:

{"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"}

...并且正在使用以下脚本在数据库表中输入数据(post_metric_score 表 -> 每个数据点一行)

         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 帖子运行相同的插入查询 6 次。

有没有办法简化上面的脚本,使其不必多次运行插入语句?

【问题讨论】:

    标签: sql json sql-server stored-procedures


    【解决方案1】:

    您可以打开 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 小提琴。

    【讨论】:

    • 谢谢@GordonLinoff,JSON 中的情绪怎么样?它们在 json 中的存在比极性和主观性更深一些,例如情绪结果。情绪。我是否必须再次打开 JSON 才能访问它们?
    • @StamatisTiniakos 。 . .不,您只需要适当地列出路径即可。
    【解决方案2】:

    另一种选择是使用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]) 
    

    【讨论】:

      猜你喜欢
      • 2011-04-06
      • 1970-01-01
      • 2014-08-28
      • 2018-08-29
      • 2013-04-19
      • 2012-10-06
      • 2016-05-19
      • 2017-01-26
      • 2019-12-10
      相关资源
      最近更新 更多