Извлечение подстроки после нахождения другой подстроки - PullRequest
0 голосов
/ 10 июля 2019

Я играл с Substring, left, right, charindex и не могу заставить это работать

Если это значение в имени столбца 'Data' (это всего одна строка)

{"email":{"RecipientId":"usertest","RecipientEmail":"test@test.com","Subject":"This is a test subject heading","RecipientSubject":"A recipient subject"}}

Как мне сделать оператор SELECT, чтобы найти заголовок 'Subject' и затем получить данные «Это объект тестирования»?Значение Subject для каждой записи различно, поэтому я просто не могу найти «Это объект тестирования».

Таким образом, конечный результат должен быть «Это объект тестирования для этого SELECT result

».

Ответы [ 2 ]

1 голос
/ 10 июля 2019

Простой и непристойный подход таков:

SELECT SUBSTRING(
                 t.YourString
                ,A.StartPosition
                ,CHARINDEX('"'
                          ,t.YourString
                          ,A.StartPosition+1) - A.StartPosition
                 )
FROM @dummyTable t
CROSS APPLY(SELECT CHARINDEX('"Subject":"',t.YourString)+11) A(StartPosition)

Я использую APPLY, чтобы вычислить значение и использовать его, как если бы вы использовали переменную. Идея такова: найти отправную точку и найти заключительную цитату оттуда. Но это будет нарушаться всякий раз, когда содержимое содержит (экранированную) цитату, как в

"Subject":"This is \"quoted\" internally"

Более общий подход

Начиная с v2016, была представлена ​​поддержка JSON. С этой (или более поздней) версией это действительно просто:

Используйте этот макет-стол для тестирования

DECLARE @dummyTable TABLE (YourString VARCHAR(1000));
INSERT INTO @dummyTable VALUES('{"email":{"RecipientId":"usertest","RecipientEmail":"test@test.com","Subject":"This is a test subject heading","RecipientSubject":"A recipient subject"}}');

- OPENJSON -метод прочитает это для вас:

SELECT JsonContent.*
FROM @dummyTable t
CROSS APPLY OPENJSON(t.YourString,'$.email') 
WITH(RecipientId VARCHAR(100)
    ,RecipientEmail VARCHAR(100)
    ,[Subject] VARCHAR(100)
    ,RecipientSubject VARCHAR(100)) JsonContent;

Но с более низкой версией вам придется обмануть это. Проще всего преобразовать JSON в атрибут, центрированный по XML , как здесь:

<email RecipientId="usertest" RecipientEmail="test@test.com" Subject="This is a test subject heading" RecipientSubject="A recipient subject" />

Мы можем достичь этого с помощью некоторых строковых методов, и я должен предупредить вас, что есть несколько ловушек с запрещенными символами и другими вещами ... Просто попробуйте:

SELECT Casted.ToXml.value('(/email/@RecipientId)[1]','varchar(1000)') AS RecipientId
      ,Casted.ToXml.value('(/email/@RecipientEmail)[1]','varchar(1000)') AS RecipientEmail
      ,Casted.ToXml.value('(/email/@Subject)[1]','varchar(1000)') AS [Subject]
      ,Casted.ToXml.value('(/email/@RecipientSubject)[1]','varchar(1000)') AS RecipientSubject
      ,Casted.ToXml.query('.') LookHowThisWasTransformed
FROM @dummyTable t 
CROSS APPLY
(
    SELECT CAST(CONCAT('<email '
                      ,REPLACE(REPLACE(REPLACE(REPLACE(t.YourString,'{"email":{"',''),'}}',''),'","','" '),'":"',' ="')
                      ,' />') AS XML)
) Casted(ToXml);
1 голос
/ 10 июля 2019

Следующий запрос должен делать то, что вы хотите:

declare @string varchar(max);
set @string = '{"email":{"RecipientId":"usertest","RecipientEmail":"test@test.com","Subject":"This is a test subject heading","RecipientSubject":"A recipient subject"}}';

select substring(@string,charindex('"Subject":',@string)+11,charindex('"RecipientSubject"',@string)-charindex('"Subject"',@string)-13);
...