Вычитание 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
,
Возможно, в вашей таблице есть данные, которые не соответствуют формату, который, как вы заявляете, у них есть.