Вычитание CHARINDEX в SUBSTRING не работает

У меня есть значение, которое мне нужно разбить в столбце Имя: AB: ABC-ABCDE Мне нужна средняя часть, которая ABC, Я использую SUBSTRING и CHARINDEX для достижения этой цели, но я получаю сообщение об ошибке:

Msg 537, Level 16, State 2, Line 393
Invalid length parameter passed to the LEFT or SUBSTRING function.

Это происходит, когда я вычитаю CHARINDEX, чтобы получить последнее значение в SUBSTRING. Код:

SELECT PRODUCT = (SUBSTRING(Name, CHARINDEX(' ',Name)+1,CHARINDEX('-',Name)-(CHARINDEX(' ',Name)+1)))
FROM A

Что я делаю неправильно?

ОБНОВЛЕНИЕ: в таблице есть еще одно значение: 'ABC-ABC: ABCDEFG-ABCDEF GH', Это дает отрицательное значение, следовательно, почему ошибка. Результат должен быть ABCDEFG

6 ответов

Решение

Другой вариант состоит в том, чтобы "заставить" NULL с помощью NullIf()

пример

... NullIf(CHARINDEX(' ',Name),0) + 1 ...

... NullIf(CHARINDEX('-',Name),0) ...

**

РЕДАКТИРОВАТЬ- Запрошенное обновление

**

Declare @YourTable table (Name varchar(50))
Insert Into @YourTable values
( 'AB: ABC-ABCDE')
,('ABC-ABC: ABCDEFG-ABCDEF GH')

Select A.*
      ,ltrim(rtrim(left(substring(Name,charindex(':',Name+':')+1,len(Name))
           ,charindex('-',substring(Name,charindex(':',Name+':')+1,len(Name))+'-') -1
           )))
 From  @YourTable A

Возвращает

Name                          (No column name)
AB: ABC-ABCDE                 ABC
ABC-ABC: ABCDEFG-ABCDEF GH    ABCDEFG

У тебя нет места. Я считаю, что самый простой способ - просто добавить один:

SELECT PRODUCT = (SUBSTRING(Name, CHARINDEX(' ', Name + ' ') + 1, CHARINDEX('-', Name + '-') - (CHARINDEX(' ', Name + ' ') + 1)))
FROM A

Я не уверен на 100%, что вы делаете то, что хотите, но это исправит ошибку, с которой вы столкнулись.

Вы можете пойти другим путем:

DECLARE @mockup TABLE(SomeValue VARCHAR(100));
INSERT INTO @mockup VALUES('AB: ABC-ABCDE')
                         ,('CD: blah-blub')
                         ,('Wrong Value here')
                         ,('MissingEnd: isCorrect');

- Запрос выберет второй элемент из XML.

SELECT CAST('<x>' + REPlACE(REPLACE(m.SomeValue,'-',' '),' ','</x><x>') + '</x>' AS XML).value('/x[2]','nvarchar(max)')
FROM @mockup m;

Хитрость заключается в следующем: использовать некоторые замены для преобразования вашего AB: ABC-ABCDE в XML-подобный

<x>AB:</x>
<x>ABC</x>
<x>ABCDE</x>

Из этого XML мы можем легко выбрать второй элемент.

Один положительный побочный эффект: этот подход намного терпимее с плохими ценностями...

ОБНОВИТЬ

Ваши плохие ценности... Новый трюк состоит в том, чтобы вырезать все до двойной точки, используя STUFF():

DECLARE @mockup TABLE(SomeValue VARCHAR(100));
INSERT INTO @mockup VALUES('AB: ABC-ABCDE')
                         ,('CD: blah-blub')
                         ,('Wrong Value here')
                         ,('MissingEnd: isCorrect')
                         ,('ABC-ABC: ABCDEFG-ABCDEF GH');

SELECT CAST('<x>' + REPlACE(REPLACE(STUFF(m.SomeValue,1,CHARINDEX(':',m.SomeValue),''),'-',' '),' ','</x><x>') + '</x>' AS XML).value('/x[2]','nvarchar(max)')
FROM @mockup m;
      BEGIN
    DECLARE @TEXT AS VARCHAR(20)
    SET @TEXT='E1014654-1'
    SELECT SUBSTRING(@TEXT, CHARINDEX('E', @TEXT)+1, CHARINDEX('-',@TEXT)) as 'STR', 
            CAST(CHARINDEX('E', @Text)+1 AS INT) as 'val1', CAST(CHARINDEX('-', @TEXT) AS INT) as 'val2',  
            (CAST(CHARINDEX('-',@TEXT) AS INT) - CAST(CHARINDEX('E',@TEXT)+1 AS INT)) as 'SUBTR', LEN(@TEXT) as 'LEN'
END

Значения в знач1 и знач2, ​​когда я действительно вычитаю их, дают мне числовое значение, соответствующее операции.

Если вы запустите то же самое без приведения, это не приведет к тому же значению:

      BEGIN
    DECLARE @TEXT2 AS VARCHAR(20)
    SET @TEXT2='E1014654-1'
    SELECT SUBSTRING(@TEXT2, CHARINDEX('E', @TEXT2)+1, CHARINDEX('-',@TEXT2)) as 'STR', 
            CHARINDEX('E', @TEXT2)+1  as 'val1', CHARINDEX('-', @TEXT2) as 'val2',  
            CHARINDEX('-',@TEXT2)  - CHARINDEX('E',@TEXT2)+1 as 'SUBTR', LEN(@TEXT2) as 'LEN'
END

Это связано, но это работает. Я скорее вижу, что у SQL естьINSTRилиGetStrфункция, которая вернет строку, которая соответствует илиNULLесли его не существует.

Иногда есть места, где вы не ожидаете их.
Так что получите подстроку от ":" в "-" и обрезать его:

RTRIM(LTRIM(SUBSTRING(Name, CHARINDEX(':',Name)+1,CHARINDEX('-',Name)-(CHARINDEX(':',Name)+1))))

Ваш вопрос не может быть воспроизведен.

DECLARE @Name varchar(31) = 'AB: ABC-ABCDE';

SELECT SUBSTRING(@Name, CHARINDEX(' ',@Name)+1,CHARINDEX('-',@Name)-(CHARINDEX(' ',@Name)+1))

Результаты в ABC,

Возможно, в вашей таблице есть данные, которые не соответствуют формату, который, как вы заявляете, у них есть.

Другие вопросы по тегам