【问题标题】:How to trim the values passing the in clause of the select query如何修剪通过选择查询的 in 子句的值
【发布时间】:2016-12-30 07:56:07
【问题描述】:

下面是使用条件选择记录的简单 sql 查询。

--like this I have 6000 usernames
select * from tblUsers where Username in ('abc  ','xyz  ',' pqr  ',' mnop  ' );

我知道 sql 中有 LTrimRtrim 分别删除左右两边的前导尾随空格。

我想删除我提供给选择查询的所有用户名中左右两边的空格。

注意:-

  • 我想修剪我在 in 子句中传递的值。(我不想将 LTrim 和 RTrim 传递给每个传递的值)。

  • 记录中没有尾随空格,但我在子句中传递的值是从 excel 复制然后粘贴到 Visual Studio 中的。然后使用 ALT 键,我将 '(单引号)放在字符串的左右两侧。因此,一些字符串的右侧尾随有空格。

如何在select查询中使用trim函数?

我使用的是 MS SQL Server 2012

【问题讨论】:

  • 用户名中有空格吗?
  • @hot2use,在插入我们使用过的记录时C# trim(),所以我认为不会有空格
  • 是否存在包含空格的有效用户名:“此用户”或“另一个用户”?下一点:C# trim 函数删除了前导和尾随空格,那么为什么还要再次删除空格呢?您的输出/字符串应该已经是 'user name','username1','username2','abc','xyz',...
  • 你为什么不想在值上同时使用LTRIMRTRIM?这将有效地导致TRIM
  • 右侧尾随空格对in 比较没有任何影响。为什么不能在复制之前使用concatenate 函数在 Excel 中附加引号和逗号。那么你一开始就不会介绍任何东西。

标签: sql-server-2012 select


【解决方案1】:

如果我正确理解您的问题,您将从 Excel 粘贴到如下临时查询中的 IN 子句中。

尾随空格无关紧要。它仍将匹配字符串foo,没有任何尾随空格。

但您需要确保没有前导空格。

既然数据源是 Excel,为什么不直接在那里做呢?

你可以用公式

= CONCATENATE("'",TRIM(SUBSTITUTE(A1,"'","''")),"',")

然后复制结果(来自上面屏幕截图中的 B 列),只需要从最终条目中修剪掉多余的逗号。

【讨论】:

    【解决方案2】:

    你可以这样做:

    select * from tblUsers where LTRIM(RTRIM(Username)) in (ltrim(rtrim('abc')),ltrim(rtrim('xyz')),ltrim(rtrim('pqr')),ltrim(rtrim('mnop')));
    

    但是,如果您有权更新数据库。请删除 Username 字段中的所有空格。这样查询确实不好。

    【讨论】:

    • 我试过你的查询。当我通过此查询select * from tblUsers where LTRIM(RTRIM(Username)) in ('abc',' useradmin ');时,有一个用户名为useradmin的用户它不返回记录,而如果将查询重写为select * from tblUsers where Username in ('abc',' useradmin');它返回一条记录。 (注意,第二个查询中没有空格)
    • 查询列表中的值不应包含开头和结尾的空格。你应该只使用'useradmin'
    • 该函数将左右修剪DB中值的空间。所以要比较的值不能包含空格。我认为这很明显。
    • 你想用空格搜索列tblUsers吗?我不明白你什么时候想这样做!!!
    • 我想修剪我在选择查询中传递的in 子句中传递的值
    【解决方案3】:

    解决您的问题并仍然能够从用户名索引中受益的一种方法是使用持久计算列:

    设置

    -- drop table dbo.tblUsers
    create table dbo.tblUsers
    (
        UserId INT NOT NULL IDENTITY(1, 1) CONSTRAINT PK_UserTest PRIMARY KEY,
        Username NVARCHAR(64) NOT NULL,
        UsernameTrimmed AS LTRIM(RTRIM(Username)) PERSISTED
    )
    GO
    
    -- other columns may be included here with INCLUDE (col1, col2)
    CREATE INDEX IDX_UserTest ON dbo.tblUsers (UsernameTrimmed)
    GO
    
    insert into dbo.tblUsers (Username) VALUES ('abc  '),('xyz  '),(' pqr  '), (' mnop  '), ('abc'), (' useradmin '), ('etc'), (' other user ')
    GO 
    
    -- some mock data to obtain a large number of records
    insert into dbo.tblUsers (Username) 
    select top 20000 SUBSTRING(text, 1, 64) from sys.messages 
    GO
    

    测试

    -- this will use the index (index seek)
    select * from tblUsers where UsernameTrimmed in (LTRIM(RTRIM('abc')), LTRIM(RTRIM(' useradmin ')));
    

    这允许以额外空间为代价更快地检索。

    为了摆脱查询构造(以及许多LTRIMs 和RTRIMs 的丑陋),您可以将搜索到的用户推送到一个看起来像tblUsers 的表中。

    create table dbo.searchedUsers
    (
        Username NVARCHAR(64) NOT NULL,
        UsernameTrimmed AS LTRIM(RTRIM(Username)) PERSISTED
    )
    GO
    

    将原始值推入dbo.searchedUsers.Username 列,查询应如下所示:

    select U.* 
    from tblUsers AS U 
       join dbo.searchedUsers AS S ON S.UsernameTrimmed = U.UsernameTrimmed 
    

    大局

    最好在应用程序的服务层 (C#) 中正确修剪数据,以便您的表的未来客户可能依赖体面的信息。因此,在将信息插入tblUsers 和搜索用户(IN 值)时都应该执行修剪

    【讨论】:

    • 高价值的帖子。谢谢:)
    【解决方案4】:
    select * 
    from tblUsers
    where RTRIM(LTRIM(Username)) in ('abc','xyz','pqr','mnop');
    

    【讨论】:

      【解决方案5】:
      Answer: SELECT * FROM tblUsers WHERE LTRIM(RTRIM(Username)) in ('abc','xyz','pqr','mnop');
      

      但是,请注意,如果您在 WHERE 子句中包含 functions,则它违背了在该列上包含 indexes 的目的,并且将使用 scanseek

      我建议你在插入tblUsers之前清理你的数据

      【讨论】:

      • 我试过你的查询。当我通过此查询select * from tblUsers where LTRIM(RTRIM(Username)) in ('abc',' useradmin ');时,有一个用户名为useradmin的用户它不返回记录,而如果将查询重写为select * from tblUsers where Username in ('abc',' useradmin');它返回一条记录。 (注意,第二个查询中没有空格)
      • 这不是 LTRIM 和 RTRIM 的全部目的吗?您删除列中的空格?如果你想让select * from tblUsers where LTRIM(RTRIM(Username)) in ('abc',' useradmin '); 这个工作,然后删除trims
      • 啊!!!您应该做的是:在查询中提供用户名之前修剪您的用户名。您在哪里生成要搜索的值?
      【解决方案6】:

      我想你可以试试这个:

      只需将 table2 替换为您获取用户名的表名表单

        select * from tblUsers where Username in ((select distinct 
        STUFF((SELECT distinct ', ' + RTRIM(LTRIM(t1.Username))
               from table2 t1
                  FOR XML PATH(''), TYPE
                  ).value('.', 'NVARCHAR(MAX)') 
              ,1,2,'') UserName
      from table2 t) );
      

      【讨论】:

      • 你在尝试什么??请详细说明
      • 当我们从 db 中选择该值时,我已经从用户名中删除了不需要的空格,并在它们之间添加了 , 以便它们可以在“In”子句中工作。
      • 列或参数??
      • 我们从 db 中选择的参数
      • 用户名的来源不是任何表/数据库,而是手动复制粘贴的字符串。
      【解决方案7】:

      我会分两步完成:

      1) 用空白的所有字符串填充临时表

      2) 使用子选择进行选择

      create table a (a char(1))
      
      insert into a values('a')
      insert into a values('b')
      insert into a values('c')
      insert into a values('d')
      
      create table #b (atmp char(5))
      
      insert into #b values ('a  ')
      insert into #b values (' b')
      insert into #b values (' c  ')
      
      select * from a where a in (select ltrim(rtrim(atmp)) from #b)
      

      【讨论】:

        猜你喜欢
        • 2019-01-11
        • 2014-08-30
        • 2011-09-11
        • 2013-07-26
        • 1970-01-01
        • 2014-02-19
        • 2019-09-05
        • 2012-05-30
        相关资源
        最近更新 更多