在 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;