代码之家  ›  专栏  ›  技术社区  ›  Sam Holder Brian Adams

为什么SqlServer select语句会选择匹配的行以及匹配并带有尾随空格的行

  •  0
  • Sam Holder Brian Adams  · 技术社区  · 16 年前

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

    1   100
    1   1000
    

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

    4 回复  |  直到 16 年前
        1
  •  3
  •   polyglot    16 年前

    为了修改我的答案,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
    
        2
  •  2
  •   AdaTheDev    16 年前

    有趣的是,如果您使用以下选项,则此选项有效:

    select * from TestFeature1 where id LIKE '1'
    

    编辑: 经过更多的研究,我发现其他人和我们有同样的对话。看见 here . 这个特别的评论已经讨论了一半。但结果正如我们所发现的,要么像上面演示的那样使用,要么添加第二个条件来检查列的DATALENGTH和提供的值是否相同。我喜欢类似的路线。

        3
  •  1
  •   KM.    16 年前

    我真的不喜欢ID是如此大的可变长度列,我会尽量避免这种情况。但是,如果确实需要这样做,请在表中添加一个计算列,在该列前面加上管道前缀和后缀,如:

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

    您将使用如下代码:

    select * from TestFeature1 where id='|1|';
    select * from TestFeature1 where id='|1 |';
    
        4
  •  0
  •   Raj    16 年前

    this 线这是一本关于这个主题的非常有趣的书。

    拉吉