简体   繁体   English

从大字符串 SQL 中提取特定值

[英]Extracting specific value from large string SQL

I've used a combination of CHARINDEX and SUBSTRING but can't get it working.我使用了 CHARINDEX 和 SUBSTRING 的组合,但无法正常工作。

I get passed a variable in SQL that contains a lot of text but has an email in it.我在 SQL 中传递了一个变量,该变量包含大量文本,但其中包含 email。 I need to extract the email value.我需要提取 email 值。

I have to use SQL 2008.我必须使用 SQL 2008。

I'm trying to extract the value between "EmailAddress":" and ",我正在尝试提取“EmailAddress”:“”之间的值,

An example string is here:示例字符串在这里:

{  "Type":test,
   "Admin":test,
   "User":{
      "UserID":"16959191",
      "FirstName":"Test",
      "Surname":"Testa",
      "EmailAddress":"Test.Test@test.com",
      "Address":"Test"
}
}

Assuming you can't upgrade to 2016 or higher, you can use a combination of substring and charindex .假设您无法升级到 2016 或更高版本,您可以使用substringcharindex的组合。
I've used a common table expression to make it less cumbersome, but you don't have to.我使用了一个通用的表表达式来减少麻烦,但你不必这样做。

DECLARE @json varchar(4000) = '{  "Type":test,
   "Admin":test,
   "User":{
      "UserID":"16959191",
      "FirstName":"Test",
      "Surname":"Testa",
      "EmailAddress":"Test.Test@test.com",
      "Address":"Test"
}
}';

WITH CTE AS
(
    SELECT @Json as Json,
    CHARINDEX('"EmailAddress":', @json) + LEN('"EmailAddress":') As StartIndex
)

SELECT SUBSTRING(Json, StartIndex, CHARINDEX(',', json, StartIndex) - StartIndex)
FROM CTE

Result: "Test.Test@test.com"结果: "Test.Test@test.com"

The first hint is: Move to v2016 if possible to use JSON support natively.第一个提示是:如果可能,请移至 v2016,以原生使用 JSON 支持。 v2008 is absolutely outdated... v2008绝对过时了...

The second hint is: Any string action (and all my approaches below will need some string actions too), will suffer from forbidden characters, unexpected blanks or any other surprise you might find within your data.第二个提示是:任何字符串操作(以及我下面的所有方法也需要一些字符串操作),都会受到禁止字符、意外空白或您可能在数据中发现的任何其他意外的影响。

Try it like this:试试这样:

First I create a mockup scenario to simulate your issue首先,我创建一个模型场景来模拟您的问题

DECLARE @tbl TABLE(ID INT IDENTITY,YourJson NVARCHAR(MAX));
INSERT INTO @tbl VALUES
 (N'{  "Type":"test1",
   "Admin":"test1",
   "User":{
      "UserID":"16959191",
      "FirstName":"Test1",
      "Surname":"Test1a",
      "EmailAddress":"Test1.Test1@test.com",
      "Address":"Test1"
      }
}')
,(N'{  "Type":"test2",
   "Admin":"test2",
   "User":{
      "UserID":"16959191",
      "FirstName":"Test2",
      "Surname":"Test2a",
      "EmailAddress":"Test2.Test2@test.com",
      "Address":"Test2"
      }
}');

--Starting with v2016 there is JSON support --从 v2016 开始支持 JSON

SELECT JSON_VALUE(t.YourJson, '$.User.EmailAddress')
FROM @tbl t

--String-methods --use CHARINDEX AND SUBSTRING --String-methods --use CHARINDEX AND SUBSTRING

DECLARE @FirstBorder NVARCHAR(MAX)='"EMailAddress":';
DECLARE @SecondBorder NVARCHAR(MAX)='",';

SELECT t.*
      ,A.Pos1
      ,B.Pos2
      ,SUBSTRING(t.YourJson,A.Pos1,B.Pos2 - A.Pos1) AS ExtractedEMail
FROM @tbl t
OUTER APPLY(SELECT CHARINDEX(@FirstBorder,t.YourJson)+LEN(@FirstBorder)) A(Pos1)
OUTER APPLY(SELECT CHARINDEX(@SecondBorder,t.YourJson,A.Pos1)) B(Pos2);

--use a XML trick --使用 XML 技巧

SELECT CAST('<x>' + REPLACE(REPLACE((SELECT t.YourJson AS [*] FOR XML PATH('')),'"EmailAddress":','<mailAddress value='),',',' />') + '</x>' AS XML)
      .value('(/x/mailAddress/@value)[1]','nvarchar(max)')
FROM @tbl t

Some explanations:一些解释:

  • JSON-support will parse the value directly from a JSON path. JSON 支持将直接从 JSON 路径解析值。
  • For CHARINDEX AND SUBSTRING I use APPLY .对于 CHARINDEX 和 SUBSTRING 我使用APPLY The advantage is, that you can use the computed positions like a variable.优点是,您可以像变量一样使用计算出的位置。 No need to repeat the CHARINDEX statements over and over.无需一遍又一遍地重复 CHARINDEX 语句。
  • The XML approach will transform your JSON to a rather strange and ugly XML. XML 方法会将您的 JSON 转换为一个相当奇怪和丑陋的 XML。 The only sensefull element is <mailAddress> with an attribute value .唯一有意义的元素是具有属性value<mailAddress> We can use the native XML method .value() to retrieve the value you are asking for:我们可以使用本机 XML 方法.value()来检索您要求的值:

An intermediate XML looks like this:中间 XML 如下所示:

<x>{  "Type":"test1" /&gt;
       "Admin":"test1" /&gt;
       "User":{
          "UserID":"16959191" /&gt;
          "FirstName":"Test1" /&gt;
          "Surname":"Test1a" /&gt;
          <mailAddress value="Test1.Test1@test.com" />
          "Address":"Test1"
          }
    }</x>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM