Извлечение значения c из большой строки SQL - PullRequest
0 голосов
/ 21 апреля 2020

Я использовал комбинацию CHARINDEX и SUBSTRING, но не могу заставить ее работать.

Я получил переменную в SQL, которая содержит много текста, но содержит электронное письмо. Мне нужно извлечь значение электронной почты.

Мне нужно использовать SQL 2008.

Я пытаюсь извлечь значение между "EmailAddress": " и ",

Пример строки здесь:

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

Ответы [ 2 ]

1 голос
/ 21 апреля 2020

Первый совет: перейдите на v2016, если возможно, для использования поддержки JSON. v2008 абсолютно устарел ...

Второй совет: любое строковое действие (и все мои подходы ниже также потребуют некоторых строковых действий) будет страдать от запрещенных символов, неожиданных пробелов или любых других неожиданностей, которые вы можете найти в ваших данных.

Попробуйте это так:

Сначала я создаю сценарий макета для имитации вашей проблемы

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"
      }
}');

- Начиная с v2016 есть JSON поддержка

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

- Строковые методы - использовать 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);

- использовать 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

Некоторые объяснения:

  • JSON -поддержка будет анализировать значение непосредственно из пути JSON.
  • Для CHARINDEX И SUBSTRING я использую APPLY. Преимущество состоит в том, что вы можете использовать вычисленные позиции как переменную. Не нужно повторять операторы CHARINDEX снова и снова.
  • Подход XML превратит ваш JSON в довольно странный и безобразный XML. Единственный разумный элемент - <mailAddress> с атрибутом value. Мы можем использовать нативный XML метод .value() для получения значения, которое вы запрашиваете:

Промежуточное значение 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>
1 голос
/ 21 апреля 2020

Предполагая, что вы не можете перейти на 2016 или выше, вы можете использовать комбинацию substring и charindex.
Я использовал общее табличное выражение, чтобы сделать его менее громоздким, но вы не делаете должен.

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

Результат: "Test.Test@test.com"

...