【问题标题】:Identifying values that have a space识别有空格的值
【发布时间】:2018-08-10 13:18:09
【问题描述】:

我们的一个数据库表中有一些数据,其结构是这样的。

ID      NAME
1002    Total Cost         
1003    Market Price       
1004    Total Cost         
1005    Total Cost         
1006    Sales Price        
1007    Gross Price        
1008    Gross Price

在我们的 UI 中,我们有一个页面,我们可以在其中看到上表中的不同名称。问题是对于“总成本”,我们看到两条记录——一条名为“总成本”,另一条名为“总成本”(即末尾有一个额外的空格)。我无法确定多余的空间在哪里。

我总是看到 3 条记录当我执行下面的查询时,不管有多少额外的尾随空格。

SELECT * FROM AB_MASTER_DATA WHERE NAME LIKE '%Total Cost   %'

如何识别不良数据?

我们使用的是 MS SQL 2014。

【问题讨论】:

  • 查找 LTRIM 和 RTRIM
  • 您可能需要检查尾随控制字符,即 char(10)、char(13) 等。看看stackoverflow.com/questions/42958278/…
  • @dfundako 为什么?不影响唯一性...
  • 取决于您认为的“不良数据”。你想得到什么结果?

标签: sql sql-server


【解决方案1】:
  • 你假设它是一个空格
  • 尾随空格不会影响唯一性,因此使用 TRIM 的任何解决方案都会失败

所以字符串Total Cost不会受到普通空格的影响

但是,还有“其他空格”:TAB、硬空格、CR、LF 等
而且我们甚至还没有使用nvarchar

在名称列上具有 UNIQUE 约束的示例

DECLARE @UniqueTest table (
    ID int NOT NULL IDENTITY (1,1) PRIMARY KEY, 
    UniqueName varchar(100) NOT NULL UNIQUE
)

--OK so far
INSERT @UniqueTest VALUES ('Market Price')
INSERT @UniqueTest VALUES ('Total Cost')

--gives error
--INSERT @UniqueTest VALUES ('Total Cost     ') 

--tab
INSERT @UniqueTest VALUES ('Total' + CHAR(9) + 'Cost')
--hard space
INSERT @UniqueTest VALUES ('Total' + CHAR(160) + 'Cost')
-- TRAILING CR
INSERT @UniqueTest VALUES ('Total Cost' + CHAR(13))

SELECT * FROM @UniqueTest

查找不是简单字母数字或空格的行

SELECT * FROM @UniqueTest WHERE UniqueName LIKE '%[^A-Z0-9 ]%'

【讨论】:

    【解决方案2】:

    问题出在您的 UI 中,您要在其中添加数据。 如果您想确保尾随和结尾空格的安全,您应该修剪您的数据。但是您也可能遇到大写/小写字符串的问题,因此您也必须对此进行管理。 你也可以使用

    SELECT DISTINCT(*) FROM AB_MASTER_DATA WHERE TRIM(NAME) LIKE 'Total Cost'
    

    从所有满足条件的中选择一个:

    【讨论】:

      【解决方案3】:

      如您所见,尾随空格在 SQL 的字符串比较中会被忽略。这是 SQL 标准的一部分。如果要查找尾随空格,可以执行以下操作:

      WHERE CONCAT(NAME, '<') LIKE '%Total Cost <'
      

      重点是在尾随空格之后连接一些字符,因此它们不再被忽略。

      【讨论】:

        【解决方案4】:

        您可以使用以下方法识别记录:

        where name like 'Total Cost_%'
        

        '_' 是一个匹配任何字符的通配符,但需要一个字符。

        您可以通过执行以下操作来识别字符(如果是 ASCII):

        select ascii(substring(name, 11, 1))
        

        【讨论】:

          猜你喜欢
          • 2018-08-28
          • 2011-01-13
          • 2014-02-08
          • 1970-01-01
          • 2017-09-17
          • 1970-01-01
          • 1970-01-01
          • 2023-02-22
          • 2021-06-04
          相关资源
          最近更新 更多