SQL concat / +运算符表现奇怪吗?

时间:2016-09-30 17:21:56

标签: sql-server tsql

所以基本上解释我的情况我有一个程序,用户可以选择代码编号,即字母数字。这些代码作为数据类型char。

存储在我的SQL数据库中

当他们选择所需的所有代码时,程序会发送一些参数(代码就是其中之一)。代码串在一起,看起来像这样:

',01,1,A3'用逗号分隔代码等。我在前面有逗号,但将逗号更改为后面并没有改变任何内容。

@reasonCode变量是串联的原因码。

在我的where子句中,我有一个声明:

(@reasonCode = 'ALL') OR 
((@reasonCode <> 'ALL' AND (charindex(',' +     ro_reason_code, @reasonCode) > 0)))

基本上我想将结果限制为那些具有用户选择的特定原因代码的结果(以及其他参数)。我试图通过串联代码,然后使用charindex搜索它们来实现这一点,用逗号分隔。

但是我遇到了一个问题。以下是使用原因代码的几种不同变体的结果:

',1' = 625 records (correct number)  
',01' = 1015(correct number)  
',01,1 = 1640(correct number)  
',1,01' = 1015(for whatever reason it isn't picking up the 1 reason codes)  

那是我的问题。

当我把1放在01的前面时,它并没有拿到1个原因代码。但是,如果我这样做,它可以正常工作......

关于为什么会发生这种情况的任何想法? (我也试过使用concat函数并获得相同的结果,并尝试强制所有内容为char数据类型。)

最后我想得到相同的结果,无论是01,1或1,01。

2 个答案:

答案 0 :(得分:2)

我很确定这是因为您说您使用的是char类型而不是varchar。请尝试将此charindex表达式替换为:

charindex(',' + rtrim(ro_reason_code), @reasonCode)

当我在表格中使用char(2)类型而char(16)使用@reasonCode时,我可以重现您的结果,我发现添加rtrim修复了问题。但不幸的是,我无法准确解释这里到底发生了什么,为什么在字符串末尾有',1'应该没有修剪,而在开头没有它。希望有人可以提供一个更深入的答案,进入“为什么”,但我想我仍然会暂时发布这个让你跑步。

繁殖:

-- Forgive the "hackish" way of populating this table. I'm assuming sysobjects has >=1015 records.
declare @Code table (ro_reason_code char(2));
insert @Code select top 625 '1' from sysobjects;
insert @Code select top 1015 '01' from sysobjects;

declare @reasonCode char(16); 

set @reasonCode = ',1,01';
select count(1) from @Code where @reasonCode = 'ALL' or charindex(',' + ro_reason_code, @reasonCode) > 0;        -- Result: 1015
select count(1) from @Code where @reasonCode = 'ALL' or charindex(',' + rtrim(ro_reason_code), @reasonCode) > 0; -- Result: 1640

set @reasonCode = ',01,1';
select count(1) from @Code where @reasonCode = 'ALL' or charindex(',' + ro_reason_code, @reasonCode) > 0;        -- Result: 1640
select count(1) from @Code where @reasonCode = 'ALL' or charindex(',' + rtrim(ro_reason_code), @reasonCode) > 0; -- Result: 1640

答案 1 :(得分:2)

因为您使用的是char,它是一个固定长度的字段,所以您的数据将被填充到字段的长度。因此'1'存储为'1 '

DECLARE @Code CHAR(2)
SET @Code = '1'

SELECT '''' + @Code + ''''
-- Printes '1 '

出于这个原因,当你添加&#39;,&#39;对于该值,您现在有',1 '(注意尾随空格)

DECLARE @Code CHAR(2)
SET @Code = '1'

SELECT '''' + ',' + @Code + ''''
-- prints ',1 '

现在,如果您要比较另一个字段,如果字符数据小于字段长度,则还会有填充空格。那么看起来像',11,1'的东西实际上类似于',11,1 ',它与',1 '的模式匹配

但是,当您撤销订单时,',1,11'变为',1,11 ',与',1 '的模式不匹配

相依

我只想指出实施存在一个微妙的问题。只需附加前导逗号,您可能会根据数据得到误报。例如,,2将匹配模式,25

,2符合1,11,25,A01

您必须在评估的每一方的两边附加逗号。

CHARINDEX( ',' + RTRIM(ro_reason_code) + ',',
           ',' + RTRIM(@reasonCode)    + ',') > 0

因此,为了说明差异,

,2,,1,11,25,A01,

不符