为什么SqlServer选择语句选择匹配的行和匹配并具有尾随空格的行

时间:2009-07-17 13:35:46

标签: sql sql-server select

我创建了一个表:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[TestFeature1](
[Id] [nvarchar](50) NOT NULL,
[Leng] [decimal](18, 0) NOT NULL
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF

我用这个插入数据:

insert into TestFeature1 (id,leng) values ('1',100);
insert into TestFeature1 (id,leng) values ('1 ',1000);

当我从表格中选择时:

select * from TestFeature1 where id='1';

这会返回2行

1   100
1   1000

为什么会这样?为什么即使查询指定值本身只有1而没有空格,它也会返回带有空格的版本?

4 个答案:

答案 0 :(得分:3)

为了重新修改我的答案,LEN()测试ANSI_PADDING是不安全的,因为它被定义为返回不包括尾随空格的长度,而DATALENGTH()是优选的,如AdaTheDev所说。

有趣的是,ANSI_PADDING是一个插入时间设置,它适用于VARCHAR但不适用于NVARCHAR。

其次,如果返回带有尾随空格的列,或者使用'='表示相等性,则似乎会发生隐含的尾随空格截断。

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING OFF
GO
CREATE TABLE [dbo].[TestFeature1](
[Id] [varchar](50) NOT NULL,
[Leng] [decimal](18, 0) NOT NULL
) ON [PRIMARY]

GO

insert into TestFeature1 (id,leng) values ('1',100); insert into TestFeature1 (id,leng) values ('1 ',1000);

-- verify no spaces inserted at end
select '['+id+']', * from TestFeature1
select datalength(id), * from TestFeature1
go

DROP TABLE [dbo].[TestFeature1]
go
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING OFF
GO
CREATE TABLE [dbo].[TestFeature1](
[Id] [nvarchar](50) NOT NULL,
[Leng] [decimal](18, 0) NOT NULL
) ON [PRIMARY]

GO

insert into TestFeature1 (id,leng) values ('1',100); insert into TestFeature1 (id,leng) values ('1 ',1000);

-- verify spaces inserted at end, and ANSI_PADDING OFF was not honoured by NVARCHAR
select '['+id+']', * from TestFeature1
select datalength(id), * from TestFeature1
go

答案 1 :(得分:2)

有趣的是,如果你使用LIKE:

select * from TestFeature1 where id LIKE '1'

编辑:经过一番研究后,我发现其他人与我们进行了同样的对话。见here。这个特别的评论是讨论的一半。但结果如我们所发现的那样,如上所示使用LIKE,或者添加第二个条件来检查列的DATALENGTH,并且提供的值是相同的。我更喜欢LIKE路线。

答案 2 :(得分:1)

我真的不喜欢ID这么大的可变长度列,我会尽量避免这种情况。但是,如果您确实需要这样做,请将一个计算列添加到您的表的前缀,并使用以下管道作为后缀:

ALTER TABLE TestFeature1 ADD
    IDx  AS '|'+ID+'|' PERSISTED 

这会强制将整个字符串相互比较,因为永远不会有任何前导或尾随字符。你也可以为此编制索引。

你会使用这样的代码:

select * from TestFeature1 where id='|1|';
select * from TestFeature1 where id='|1 |';

答案 3 :(得分:0)

查找this个帖子。对这个主题做了一个非常有趣的阅读。

拉​​吉