在 SUBSTRING 中减去 CHARINDEX 不起作用
Subtraction of CHARINDEX in SUBSTRING is not working
我有一个值需要在名称列中分解: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
我做错了什么?
更新:table 中还有另一个值,例如:'ABC-ABC: ABCDEFG-ABCDEF GH'
。这给出了负值,因此是错误的原因。结果应该是 ABCDEFG
你没有space。我发现最简单的方法是只加一个:
SELECT PRODUCT = (SUBSTRING(Name, CHARINDEX(' ', Name + ' ') + 1, CHARINDEX('-', Name + '-') - (CHARINDEX(' ', Name + ' ') + 1)))
FROM A
我不是 100% 确定这是否符合您的要求,但它会修复您遇到的错误。
另一种选择是 "force" 带有 NullIf()
的 NULL
例子
... NullIf(CHARINDEX(' ',Name),0) + 1 ...
... NullIf(CHARINDEX('-',Name),0) ...
**
EDIT- Requested Update
**
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
Returns
Name (No column name)
AB: ABC-ABCDE ABC
ABC-ABC: ABCDEFG-ABCDEF GH ABCDEFG
您的问题无法重现。
DECLARE @Name varchar(31) = 'AB: ABC-ABCDE';
SELECT SUBSTRING(@Name, CHARINDEX(' ',@Name)+1,CHARINDEX('-',@Name)-(CHARINDEX(' ',@Name)+1))
结果 ABC
。
可能您的 table 中有一些数据不符合您声明的格式。
有时会有一些您不希望出现的空间。
所以得到从 ":"
到 "-"
和 trim 的子串:
RTRIM(LTRIM(SUBSTRING(Name, CHARINDEX(':',Name)+1,CHARINDEX('-',Name)-(CHARINDEX(':',Name)+1))))
你可能会走另一条路:
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 like
<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;
我有一个值需要在名称列中分解: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
我做错了什么?
更新:table 中还有另一个值,例如:'ABC-ABC: ABCDEFG-ABCDEF GH'
。这给出了负值,因此是错误的原因。结果应该是 ABCDEFG
你没有space。我发现最简单的方法是只加一个:
SELECT PRODUCT = (SUBSTRING(Name, CHARINDEX(' ', Name + ' ') + 1, CHARINDEX('-', Name + '-') - (CHARINDEX(' ', Name + ' ') + 1)))
FROM A
我不是 100% 确定这是否符合您的要求,但它会修复您遇到的错误。
另一种选择是 "force" 带有 NullIf()
例子
... NullIf(CHARINDEX(' ',Name),0) + 1 ...
... NullIf(CHARINDEX('-',Name),0) ...
**
EDIT- Requested Update
**
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
Returns
Name (No column name)
AB: ABC-ABCDE ABC
ABC-ABC: ABCDEFG-ABCDEF GH ABCDEFG
您的问题无法重现。
DECLARE @Name varchar(31) = 'AB: ABC-ABCDE';
SELECT SUBSTRING(@Name, CHARINDEX(' ',@Name)+1,CHARINDEX('-',@Name)-(CHARINDEX(' ',@Name)+1))
结果 ABC
。
可能您的 table 中有一些数据不符合您声明的格式。
有时会有一些您不希望出现的空间。
所以得到从 ":"
到 "-"
和 trim 的子串:
RTRIM(LTRIM(SUBSTRING(Name, CHARINDEX(':',Name)+1,CHARINDEX('-',Name)-(CHARINDEX(':',Name)+1))))
你可能会走另一条路:
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 like
<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;