简体   繁体   中英

SQL Select String between Two Strings

I have been attempting gather the text between the two strings below, however not all of the rows contain either of the strings and it returns the following error;

Msg 537, Level 16, State 5, Line 22
Invalid length parameter passed to the LEFT or SUBSTRING function

I can't seem to amend the code to allow for fields where either string is not contained in the select column, and to return Null if this is the case.

DECLARE @FirstPatn CHAR(3)
DECLARE @SecondPatn CHAR(3)

SET @FirstPatn = 'EMR'
SET @SecondPatn = ' - '

SELECT  
    @start = PATINDEX('%' + @FirstPatn + '%', ActionDescription),
    @end = PATINDEX('%' + @secondPatn + '%', ActionDescription)
FROM
    Temp.TicketActions

SELECT  
    SUBSTRING(ActionDescription, @start + LEN(@firstpatn), ( @end - @start ) - LEN(@secondpatn))
FROM
    Temp.TicketActions

Please find some sample data below;

Arran LBS - EMR00524 - Packet loss

Email: RE: Arran LBS - EMR00524 - No Sync (connection affected: na2311@rTest..biz) [#3314184] (11/06/15 17:03)

RE: Arran LBS - EMR00524 - No Sync

RE: Arran LBS - EMR00524 - No Syn (connection affected: na23Test1@rnli.biz)

Automatic Unpark

Broadband Regrade

This Ticket has been resolved.

domain query

The big problem is that you are getting the patindex of @SecondPatn , even if it occurs before @FirstPatn . This is the root cause of our error. This is because all of the example records that contain @FirstPatn have an occurrence of @SecondPatn prior to the first occurance of @FirstPatn

We want to set our end point to the beginning position of @SecondPatn , but only when it is found after @FirstPatn .

The other issue in the query was mentioned in a comment by Giorgos - @start and @end are fixed values in your query. These need to change as the string we are considering will change row by row.

This example uses the sample data you provided. It returns the string and code we are looking for. I increased the length of one of the strings we are looking for in order to show this will work with variable lengths. You can run this to test, then modify to work with your schema. You did not specify the desired result, so I am assuming based on your query.

setup:

declare @test table (
id int,
ActionDescription varchar(max)
)

insert into @test
values
(1, 'Arran LBS - EMR00524 - Packet loss'),
(2, 'Email: RE: Arran LBS - EMR00524 - No Sync (connection affected: na2311@rTest..biz) [#3314184] (11/06/15 17:03)'),
(3, 'RE: Arran LBS - EMR0052467 - No Sync'),
(4, 'RE: Arran LBS - EMR00524 - No Syn (connection affected: na23Test1@rnli.biz)'),
(5, 'Automatic Unpark'),
(6, 'Broadband Regrade'),
(7, 'This Ticket has been resolved.'),
(8, 'domain query')

Query:

declare @FirstPatn char(3)
declare @SecondPatn char(3)

set @FirstPatn = 'EMR'
set @SecondPatn = ' - ';

select  sub.ActionDescription,
        sub.TicketActions
from (
    select  
        ActionDescription,
            -- set value to null when first pattern not found
        case when patindex('%' + @FirstPatn + '%', ActionDescription) = 0
            then null 
            else 
                substring(              
                ActionDescription,
                    --start position is after our first pattern
                (patindex('%' + @FirstPatn + '%', ActionDescription)) + len(@FirstPatn),
                    -- end position is start position of second pattern, only when second pattern is found AFTER first pattern
                patindex('%' + @secondPatn + '%',right(ActionDescription, len(ActionDescription) - (patindex('%' + @FirstPatn + '%', ActionDescription) + len(@FirstPatn) - 1)))        
            ) 
        end TicketActions
    from @test
)sub
where sub.TicketActions is not null

result:

+---------------+----------------------------------------------------------------------------------------------------------------+
| TicketActions |                                               ActionDescription                                                |
+---------------+----------------------------------------------------------------------------------------------------------------+
|        00524  | Arran LBS - EMR00524 - Packet loss                                                                             |
|        00524  | Email: RE: Arran LBS - EMR00524 - No Sync (connection affected: na2311@rTest..biz) [#3314184] (11/06/15 17:03) |
|      0052467  | RE: Arran LBS - EMR0052467 - No Sync                                                                           |
|        00524  | RE: Arran LBS - EMR00524 - No Syn (connection affected: na23Test1@rnli.biz)                                    |
+---------------+----------------------------------------------------------------------------------------------------------------+

To return nulls when our string is not found, simply remove the outer query:

declare @FirstPatn char(3)
declare @SecondPatn char(3)

set @FirstPatn = 'EMR'
set @SecondPatn = ' - ';

select  
    -- set value to null when first pattern not found
    case when patindex('%' + @FirstPatn + '%', ActionDescription) = 0
        then null 
        else 
            substring(              
            ActionDescription,
            --start position is after our first pattern
            (patindex('%' + @FirstPatn + '%', ActionDescription)) + len(@FirstPatn),
            -- end position is start position of second pattern, only when second pattern is found AFTER first pattern
            patindex('%' + @secondPatn + '%',right(ActionDescription, len(ActionDescription) - (patindex('%' + @FirstPatn + '%', ActionDescription) + len(@FirstPatn) - 1)))        
            ) 
    end TicketActions,
    ActionDescription
from @test

returns

+---------------+----------------------------------------------------------------------------------------------------------------+
| TicketActions |                                               ActionDescription                                                |
+---------------+----------------------------------------------------------------------------------------------------------------+
| 00524         | Arran LBS - EMR00524 - Packet loss                                                                             |
| 00524         | Email: RE: Arran LBS - EMR00524 - No Sync (connection affected: na2311@rTest..biz) [#3314184] (11/06/15 17:03) |
| 0052467       | RE: Arran LBS - EMR0052467 - No Sync                                                                           |
| 00524         | RE: Arran LBS - EMR00524 - No Syn (connection affected: na23Test1@rnli.biz)                                    |
| NULL          | Automatic Unpark                                                                                               |
| NULL          | Broadband Regrade                                                                                              |
| NULL          | This Ticket has been resolved.                                                                                 |
| NULL          | domain query                                                                                                   |
+---------------+----------------------------------------------------------------------------------------------------------------+

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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