【问题标题】:How to extract specific text from column如何从列中提取特定文本
【发布时间】:2021-03-18 08:23:16
【问题描述】:

我正在使用 SQL Server 2016,我在其中一个 nvarchar(max) 类型列中加载 JSON 响应。 现在我想创建一个派生列,甚至是一个视图,它会在完整的 JSON 响应中找到特定值,并仅在新的派生列中显示该值。

例子:

**Complete_JSON_Repsone**  --> this is SQL column
{"result":{"banner_image_light":"","country":"USA","parent":"","notes":"","stock_symbol":"","u_op_dev_version":"","u_restriciton":"No","discount":"","sys_id":"7a2c008c1b07ac50a62cea0ce54bcbe8","market_cap":"0","customer":"false"}}

我尝试了下面的查询,但它没有给出预期的结果它打印出sys_id之后的所有内容:

SELECT 
   Substring (
      a.Complete_JSON_Repsone, 
      Charindex( '"sys_id":', Complete_JSON_Repsone) + 1, 
      Len(Complete_JSON_Repsone) 
   ) AS [Sys_Idd] 
FROM <table-name> a

当前输出(实际结果):

Sys_Idd
sys_id":"7a2c008c1b07ac50a62cea0ce54bcbe8","market_cap":"0","customer":"false"}}      

预期输出:

 Sys_Idd
 7a2c008c1b07ac50a62cea0ce54bcbe8

更新

示例输入:

Create table dbo.log1
(
  Id varchar(50),
  Complete_JSON_Response nvarchar(max),
  Sys_Id varchar(50)
)


insert into dbo.log1 (Id,Complete_JSON_Response) 
values ('S1','{"result":{"banner_image_light":"","country":"USA","parent":"","notes":"","stock_symbol":"","u_op_dev_version":"","u_restriciton":"No","discount":"","sys_id":"7a2c008c1b07ac50a62cea0ce54bcbe8","market_cap":"0","customer":"false"}}')
,('S2','{"result":{"banner_image_light":"","country":"Aus","parent":"","notes":"","stock_symbol":"","u_op_prod_version":"","u_restriciton":"No","discount":"","sys_id":"5b2c008c1b07ac50a62cea0ce54bcbe8","market_cap":"1","customer":"TRUE"}}')

select * from dbo.log1

在上面的选择查询打印中,Sys_id 列的 NULL 值作为该列的值,最初未插入。我在预期输出中想要的是,它应该只填充(导出)从 Complete_JSON_Response 列到 Sys_id 列的 sys_id 值,而不是 NULL

预期输出:

Id    Sys_Id
S1   7a2c008c1b07ac50a62cea0ce54bcbe8
S2   5b2c008c1b07ac50a62cea0ce54bcbe8

【问题讨论】:

  • 当您说 JSON 是动态的时,它的动态是什么?按键和整体结构至少保持不变吗?你用的是SQL2016+吗?
  • @Charlieface 我已经更新了我的第一篇文章。请检查我的确切要求。谢谢。
  • JSON_VALUE 应该为您解决问题,它不起作用吗?

标签: sql json sql-server tsql


【解决方案1】:

SQL Server 2016 支持 JSON,所以你可以尝试使用JSON_VALUE():

SELECT JSON_VALUE(Complete_JSON_Response, '$.result.sys_id') AS sys_id
FROM (VALUES
   (N'{
   "result":{
      "banner_image_light":"",
      "country":"USA",
      "parent":"",
      "notes":"",
      "stock_symbol":"",
      "u_op_dev_version":"",
      "u_restriciton":"No",
      "discount":"",
      "sys_id":"7a2c008c1b07ac50a62cea0ce54bcbe8",
      "market_cap":"0",
      "customer":"false"
   }
   }')
) a (Complete_JSON_Response)

作为附加选项,您可以使用递归搜索创建简化的 UDF:

CREATE FUNCTION dbo.ParseJson (
    @json nvarchar(max),
    @key nvarchar(max)
)
RETURNS @ResultTable TABLE (
   [value] nvarchar(max)
)
AS
BEGIN
   ;WITH rCTE AS (
      SELECT 
          CONVERT(nvarchar(max), N'$') COLLATE DATABASE_DEFAULT AS [path], 
          CONVERT(nvarchar(max), JSON_QUERY(@json, '$')) COLLATE DATABASE_DEFAULT AS [value]
      UNION ALL
      SELECT 
         CONVERT(nvarchar(max), c.[key]) COLLATE DATABASE_DEFAULT,
         CONVERT(nvarchar(max), c.[value]) COLLATE DATABASE_DEFAULT                                        
      FROM rCTE r
      CROSS APPLY OPENJSON(r.[value]) c
      WHERE ISJSON(r.[value]) = 1
   )
   INSERT INTO @ResultTable ([value])
   SELECT [value]
   FROM rCTE
   WHERE (ISJSON([value]) = 0) AND (path = @key)
   
   RETURN
END

声明:

DECLARE @json nvarchar(max) = N'
   {
   "result":{
      "banner_image_light":"",
      "country":"USA",
      "parent":"",
      "notes":"",
      "stock_symbol":"",
      "u_op_dev_version":"",
      "u_restriciton":"No",
      "discount":"",
      "sys_id":"7a2c008c1b07ac50a62cea0ce54bcbe8",
      "market_cap":"0",
      "customer":"false"
   },
   "result2":{
      "sys_id":"xxxx008c1b07ac50a62cea0ce54bcbe8"
   }
   }
'

SELECT j.[value] AS sys_id
FROM (VALUES (@json)) a (Complete_JSON_Response)
OUTER APPLY dbo.ParseJson(a.Complete_JSON_Response, 'sys_id') j

结果:

sys_id
--------------------------------
xxxx008c1b07ac50a62cea0ce54bcbe8
7a2c008c1b07ac50a62cea0ce54bcbe8

【讨论】:

  • 谢谢@Zhorov 但在这种情况下,JSON 值是硬编码的,就像我说的 Complete_JSON_Repsone 列中的值已经像日志一样写入,并且每一行都是动态的。
  • @VikasJ 其他可能的 JSON 内容是什么?我认为将此内容解析为 JSON 应该是您的首选。
  • 看起来很完美@Zhorov
  • @Zhorov 我已经更新了我的第一篇文章。请检查我的确切要求。谢谢。
  • @VikasJ 很简单的UPDATE: UPDATE dbo.log1 SET Sys_Id = JSON_VALUE(Complete_JSON_Response, '$.result.sys_id')
【解决方案2】:

你可以使用一个函数。它可能会导致一些性能问题,但工作正常。

select
'{"result":{"banner_image_light":"","country":"USA","parent":"","notes":"","stock_symbol":"","u_op_dev_version":"","u_restriciton":"No","discount":"","sys_id":"7a2c008c1b07ac50a62cea0ce54bcbe8","market_cap":"0","customer":"false"}}' json
into tmp_json



CREATE FUNCTION dbo.trialFnc(
    @json nvarchar(max),
    @key nvarchar(255)
)
RETURNS nvarchar(255)
AS 
BEGIN
    declare @txt1 nvarchar(max) = right(@json, len(@json) - (charindex(@key, @json)) + 1 - len(@key) - 3)
    declare @txt2 nvarchar(max) = left(@txt1, charindex('"', @txt1) - 1)

    RETURN @txt2
END;   


select
    dbo.trialFnc(json, 'country') country
,   dbo.trialFnc(json, 'sys_id') sys_id
from tmp_json

它会返回给你:

country sys_id
USA 7a2c008c1b07ac50a62cea0ce54bcbe8

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-10
    • 2019-12-08
    相关资源
    最近更新 更多