【问题标题】:SQL Server 2016 JSON in existing column现有列中的 SQL Server 2016 JSON
【发布时间】:2016-10-18 01:26:22
【问题描述】:

我一直在用头撞墙,这可能是相当明显的事情,但没有多少谷歌搜索为我提供了答案或我需要的提示。希望这里的天才可以帮助我:)

我有一个看起来有点像这样的表:

JSON 已经在我的 SQL Server 表中,基本上是一个篮子的产品内容。当前行,是整个购买的交易,JSON 是每个产品及其各种属性的另一个子集。

这里以 2 行 JSON 字符串为例:

[{"id":"429ac4e546-11e6-471e","product_id":"dc85bff3ecb24","register_id":"0adaaf5c4a65e37c7","sequence":"0","handle":"Skirts","sku":"20052","name":"Skirts","quantity":1,"price":5,"cost":0,"price_set":1,"discount":-5,"loyalty_value":0.2,"tax":0,"tax_id":"dc85058a-a69e-11e58394d","tax_name":"No Tax","tax_rate":0,"tax_total":0,"price_total":5,"display_retail_price_tax_inclusive":"1","status":"CONFIRMED","attributes":[{"name":"line_note","value":""}]}]

[{"id":"09237884-9713-9b6751fe0b85ffd","product_id":"dc85058a-a66b4c06702e13","register_id":"06bf5b9-31e2b4ac9d0a","sequence":"0","handle":"BricaBrac","sku":"20076","name":"Bric a Brac","quantity":1,"price":7,"cost":0,"price_set":1,"discount":-7,"loyalty_value":0.28,"tax":0,"tax_id":"dc85058a-2-54f20388394d","tax_name":"No Tax","tax_rate":0,"tax_total":0,"price_total":7,"display_retail_price_tax_inclusive":"1","status":"CONFIRMED","attributes":[{"name":"line_note","value":""}]},{"id":"09237884-9713-9b601235370","product_id":"dc85058a-a6fe112-6b4bfafb107e","register_id":"06bf537bf6b9-31e2b4ac9d0a","sequence":"1","handle":"LadiesTops","sku":"20040","name":"Ladies Tops","quantity":1,"price":10,"cost":0,"price_set":1,"discount":-10,"loyalty_value":0.4,"tax":0,"tax_id":"dc85058a-a690388394d","tax_name":"No Tax","tax_rate":0,"tax_total":0,"price_total":10,"display_retail_price_tax_inclusive":"1","status":"CONFIRMED","attributes":[{"name":"line_note","value":""}]},{"id":"09237884-9713-9b52007fa6c7d","product_id":"dc85058a-a6fa-b4c06d7ed5a","register_id":"06bf537b-cf6b9-31e2b4ac9d0a","sequence":"2","handle":"DVD","sku":"20077","name":"DVD","quantity":1,"price":3,"cost":0,"price_set":1,"discount":-3,"loyalty_value":0.12,"tax":0,"tax_id":"dc85058a-e5-e112-54f20388394d","tax_name":"No Tax","tax_rate":0,"tax_total":0,"price_total":3,"display_retail_price_tax_inclusive":"1","status":"CONFIRMED","attributes":[{"name":"line_note","value":""}]}]

所以我想要实现的是从该列中的数据创建一个新表。 (然后我可以通过 id 字段中的唯一字符串将产品表连接到第一个表)。

是否可以使用 sql2016 中的新原生 JSON 来做到这一点。

我的替代方法是通过 SSIS 使用插件来完成,但如果我可以使用 SQL Server 本身内部的存储过程来完成它会更简洁。

提前致谢!

【问题讨论】:

  • 你能添加预期的输出吗

标签: sql sql-server json sql-server-2016


【解决方案1】:

这是使用OPENJSON 从您的JSON 中提取ID 的一种方法

SELECT  id
FROM Yourtable
CROSS apply Openjson([register_sale_products])
 WITH (id varchar(500) 'lax $.id') 

OPENJSON中有两种路径模式

  1. 打击
  2. 松懈

Strict : 当propertypath未找到 时会抛出错误

lax:当propertypath找不到时,这将返回NULL。如果您没有提及任何模式,则默认使用Lax

您可以根据自己的需要使用上述模式

演示:

架构设置

CREATE TABLE json_test
  (
     json_col VARCHAR(8000)
  )

样本数据

INSERT INTO json_test
VALUES      ('[{"id":"429ac4e546-11e6-471e","product_id":"dc85bff3ecb24","register_id":"0adaaf5c4a65e37c7","sequence":"0","handle":"Skirts","sku":"20052","name":"Skirts","quantity":1,"price":5,"cost":0,"price_set":1,"discount":-5,"loyalty_value":0.2,"tax":0,"tax_id":"dc85058a-a69e-11e58394d","tax_name":"No Tax","tax_rate":0,"tax_total":0,"price_total":5,"display_retail_price_tax_inclusive":"1","status":"CONFIRMED","attributes":[{"name":"line_note","value":""}]}]'),
            ('[{"id":"09237884-9713-9b6751fe0b85ffd","product_id":"dc85058a-a66b4c06702e13","register_id":"06bf5b9-31e2b4ac9d0a","sequence":"0","handle":"BricaBrac","sku":"20076","name":"Bric a Brac","quantity":1,"price":7,"cost":0,"price_set":1,"discount":-7,"loyalty_value":0.28,"tax":0,"tax_id":"dc85058a-2-54f20388394d","tax_name":"No Tax","tax_rate":0,"tax_total":0,"price_total":7,"display_retail_price_tax_inclusive":"1","status":"CONFIRMED","attributes":[{"name":"line_note","value":""}]},{"id":"09237884-9713-9b601235370","product_id":"dc85058a-a6fe112-6b4bfafb107e","register_id":"06bf537bf6b9-31e2b4ac9d0a","sequence":"1","handle":"LadiesTops","sku":"20040","name":"Ladies Tops","quantity":1,"price":10,"cost":0,"price_set":1,"discount":-10,"loyalty_value":0.4,"tax":0,"tax_id":"dc85058a-a690388394d","tax_name":"No Tax","tax_rate":0,"tax_total":0,"price_total":10,"display_retail_price_tax_inclusive":"1","status":"CONFIRMED","attributes":[{"name":"line_note","value":""}]},{"id":"09237884-9713-9b52007fa6c7d","product_id":"dc85058a-a6fa-b4c06d7ed5a","register_id":"06bf537b-cf6b9-31e2b4ac9d0a","sequence":"2","handle":"DVD","sku":"20077","name":"DVD","quantity":1,"price":3,"cost":0,"price_set":1,"discount":-3,"loyalty_value":0.12,"tax":0,"tax_id":"dc85058a-e5-e112-54f20388394d","tax_name":"No Tax","tax_rate":0,"tax_total":0,"price_total":3,"display_retail_price_tax_inclusive":"1","status":"CONFIRMED","attributes":[{"name":"line_note","value":""}]}]')

查询

SELECT  id
FROM json_test
CROSS apply Openjson(json_col)
      WITH (id varchar(500) 'lax $.id')

结果:

╔═══════════════════════════════╗
║              id               ║
╠═══════════════════════════════╣
║ 429ac4e546-11e6-471e          ║
║ 09237884-9713-9b6751fe0b85ffd ║
║ 09237884-9713-9b601235370     ║
║ 09237884-9713-9b52007fa6c7d   ║
║ 429ac4e546-11e6-471e          ║
║ 09237884-9713-9b6751fe0b85ffd ║
║ 09237884-9713-9b601235370     ║
║ 09237884-9713-9b52007fa6c7d   ║
╚═══════════════════════════════╝

【讨论】:

  • 谢谢!非常感谢。这让我成为了其中的一部分。但是,我想将 JSON 字符串的所有部分作为表返回,而不仅仅是 ID 列。这可能吗?
  • 我觉得你给我的东西足以让我创造一个解决方案!现在正在处理,如果可行,会发回..
  • 是的,多亏了你的帮助,我有了解决方案。将发布为帮助他人的答案。
【解决方案2】:

感谢 Prdp 的回复,引导我找到答案,如下所示。

SELECT  a.ID, b.*  -- select ID from original table for proofing, and all from table b
FROM reporttest a  -- table name with alias
CROSS apply Openjson([register_sale_products])  -- column name
  WITH (
    id nvarchar(200) '$.id',
    product_id nvarchar(200) '$.product_id',
    register_id nvarchar(200) '$.register_id',
    sequence nvarchar(200) '$.sequence',
    handle nvarchar(200) '$.handle',
    sku nvarchar(200) '$.sku',
    name nvarchar(200) '$.name',
    quantity nvarchar(200) '$.quantity',
    price nvarchar(200) '$.price',
    cost nvarchar(200) '$.cost',
    price_set nvarchar(200) '$.price_set',
    discount nvarchar(200) '$.discount',
    loyalty_value nvarchar(200) '$.loyalty_value',
    tax nvarchar(200) '$.tax',
    tax_id nvarchar(200) '$.tax_id',
    tax_name nvarchar(200) '$.tax_name',
    --No Tax nvarchar(200) '$.No Tax',
    tax_rate nvarchar(200) '$.tax_rate',
    tax_total nvarchar(200) '$.tax_total',
    price_total nvarchar(200) '$.price_total',
    display_retail_price_tax_inclusive nvarchar(200) '$.display_retail_price_tax_inclusive',
    status nvarchar(200) '$.status',
    CONFIRMED nvarchar(200) '$.CONFIRMED',
    attributes nvarchar(200) '$.attributes',
    name nvarchar(200) '$.name',
    line_note nvarchar(200) '$.line_note',
    value nvarchar(200) '$.value'     
        ) b  -- alias the "with" section as table b

【讨论】:

    【解决方案3】:

    用简单的 sql 查询一点点努力,你就会到达那里。

    将此查询作为存储过程并在需要时调用它..

    根据您的要求编辑此查询。

    将 '%id":"' 更改为 '%anything_inside_the_string' 你会得到值.. :)

    DECLARE @LOOP_1 INT=1,@NAME NVARCHAR (MAX),@LEFT NVARCHAR(MAX),@loop_2 int=0
    SET @NAME='[{"id":"429ac4e546-11e6-471e","product_id":"dc85bff3ecb24","register_id":"0adaaf5c4a65e37c7","sequence":"0","handle":"Skirts","sku":"20052","name":"Skirts","quantity":1,"price":5,"cost":0,"price_set":1,"discount":-5,"loyalty_value":0.2,"tax":0,"tax_id":"dc85058a-a69e-11e58394d","tax_name":"No Tax","tax_rate":0,"tax_total":0,"price_total":5,"display_retail_price_tax_inclusive":"1","status":"CONFIRMED","attributes":[{"name":"line_note","value":""}]}]'
    
    -- First loop started to find where 'id":"' is located
    WHILE @LOOP_1!=(SELECT LEN(@NAME))
    BEGIN
        SET @LEFT=(LEFT(@NAME,@LOOP_1))
        IF @LEFT LIKE '%id":"' -------- Change '%id":"' to '%product_id":"' and you will get the value.. :)
        BEGIN
    
            set @NAME=(right(@NAME,len(@name)-@LOOP_1))
    
            -- Second loop started to find where ',' is located after '"id":"'
            WHILE @loop_2!=(SELECT LEN(@NAME))
            BEGIN
    
                SET @LEFT=(LEFT(@NAME,@loop_2))
                IF @LEFT LIKE '%,'
                BEGIN
                    if left(@name,@loop_2-1)like '%"%'
                    SELECT left(@name,@loop_2-2)
                    else
                    SELECT left(@name,@loop_2-2)
                    set @loop_2=(SELECT LEN(@NAME)-1)
                    set @loop_1=@loop_2
    
                END
            SET @loop_2=@loop_2+1
            END
    
        END
        SET @LOOP_1=@LOOP_1+1
    END
    

    【讨论】:

    • 拥有原生支持的情况下为什么要这样做
    • @prdp 我正在尝试根据 Maz 的要求完成任务。他愿意尝试使用 sp 而不是原生 JSON 的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多