Вычитание CHARINDEX в SUBSTRING не работает - PullRequest
0 голосов
/ 25 января 2019

У меня есть значение, которое мне нужно разбить в столбце Имя: 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

Ответы [ 5 ]

0 голосов
/ 25 января 2019

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

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;
0 голосов
/ 25 января 2019

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

RTRIM(LTRIM(SUBSTRING(Name, CHARINDEX(':',Name)+1,CHARINDEX('-',Name)-(CHARINDEX(':',Name)+1))))
0 голосов
/ 25 января 2019

Другой вариант заключается в "принудительном" значении 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
0 голосов
/ 25 января 2019

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

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

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

Результат: ABC.

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

0 голосов
/ 25 января 2019

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

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

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

...