Najlepszy sposób na wyodrębnienie segmentów / wartości z pola VARCHAR w SQL opartym na SET

Weź następujące przykładowe dane:

SELECT 'HelpDesk Call Reference F0012345, Call Update, 40111' AS [Subject]
UNION ALL
SELECT 'HelpDesk Call Reference F0012346, Call Resolved, 40112' AS [Subject]
UNION ALL
SELECT 'HelpDesk Call Reference F0012347, New call logged, 40113' AS [Subject]

To, co chciałbym zrobić, to wyodrębnić te dane w następujący sposób:

Jak widać, muszę wyodrębnić Ref, Type & OurRef jako oddzielne kolumny, aby zapewnić efektywny zestaw SQL oparty na zestawie podczas przetwarzania wynikowych wiadomości e-mail.

Zazwyczaj w tym scenariuszu używałbym funkcji takiej jak ta:

CREATE FUNCTION dbo.fnParseString (
    @Section SMALLINT ,
    @Delimiter CHAR ,
    @Text VARCHAR(MAX)
)
RETURNS VARCHAR(8000)
AS 
    BEGIN
        DECLARE @NextPos SMALLINT;
        DECLARE @LastPos SMALLINT;
        DECLARE @Found SMALLINT;

        SELECT  @NextPos = CHARINDEX(@Delimiter, @Text, 1) ,
                @LastPos = 0 ,
                @Found = 1

        WHILE @NextPos > 0
            AND ABS(@Section) <> @Found 
            SELECT  @LastPos = @NextPos ,
                    @NextPos = CHARINDEX(@Delimiter, @Text, @NextPos + 1) ,
                    @Found = @Found + 1

        RETURN LTRIM(RTRIM(CASE
            WHEN @Found <> ABS(@Section) OR @Section = 0 THEN NULL
            WHEN @Section > 0 THEN SUBSTRING(@Text, @LastPos + 1, CASE WHEN @NextPos = 0 THEN DATALENGTH(@Text) - @LastPos ELSE @NextPos - @LastPos - 1 END)
            ELSE SUBSTRING(@Text, @LastPos + 1, CASE WHEN @NextPos = 0 THEN DATALENGTH(@Text) - @LastPos ELSE @NextPos - @LastPos - 1 END)
        END))
    END

Na przykład i zastąpię białą spację przed ref, aby dołączyć przecinek i podzielić w następujący sposób:

WITH    ExampleData
          AS ( SELECT   'HelpDesk Call Reference F0012345, Call Update, 40111' AS [Subject]
               UNION ALL
               SELECT   'HelpDesk Call Reference F0012346, Call Resolved, 40112'
               UNION ALL
               SELECT   'HelpDesk Call Reference F0012347, New call logged, 40113'
             )
    SELECT  dbo.fnParseString(2, ',', REPLACE([Subject], 'HelpDesk Call Reference ', 'HelpDesk Call Reference, ')) AS [Ref] ,
            dbo.fnParseString(3, ',', REPLACE([Subject], 'HelpDesk Call Reference ', 'HelpDesk Call Reference, ')) AS [Type] ,
            dbo.fnParseString(4, ',', REPLACE([Subject], 'HelpDesk Call Reference ', 'HelpDesk Call Reference, ')) AS [OurRef]
    FROM    ExampleData

Jak widzisz, mam rozwiązanie, które pozwala uzyskać wynik końcowy, ale użycie niechlujnego udf nie jest idealne i zastanawiałem się, czysql-server ma lepszy sposób na robienie takich rzeczy - być może wbudowane wyrażenia regularne? To znaczy. MyślęPATINDEX() akceptuje wyrażenia regularne jako ciąg wyszukiwania - w połączeniu zSUBSTRING() mógłbym robić to, czego potrzebuję, ale naprawdę nie wiem od czego zacząć?

Edytować: Proszę zauważyć, że jest to uproszczony przykład, temat jest zmienny i dostosuję tę samą technikę do analizowania ciała, ciało będzie miało 8 elementów danych, które muszę przeanalizować przy użyciu różnych ograniczników, więc to wyklucza użycieParseName() ponieważ pozwala tylko na 4 części i nie mogę użyć stałej długości (tj.substring()) ponieważ długość będzie bardzo zróżnicowana (szczególnie, jeśli zaangażowane są różne centra informacyjne), dlatego właśnie myślałemPATINDEX() & SUBSTRING()

questionAnswers(3)

yourAnswerToTheQuestion