【问题标题】:MySQL select fields containing leading or trailing whitespaceMySQL 选择包含前导或尾随空格的字段
【发布时间】:2013-05-19 10:35:35
【问题描述】:

我可以使用 MySQL TRIM() 方法来清理包含带有 UPDATE 的前导或尾随空格的字段,如下所示:

UPDATE Foo SET field = TRIM(field);

我想在运行之前实际查看这将影响的字段。我试过了,但返回 0 个结果:

SELECT * FROM Foo WHERE field != TRIM(field);

似乎这应该有效,但它没有。

有人有解决办法吗?另外,很好奇为什么这不起作用...

【问题讨论】:

  • 看到这个答案:stackoverflow.com/a/2363449/1618257 ALSO,对于!=,试试<>
  • @David: != vs <> 似乎没有区别。
  • eggyal 解释了尾随空格。鉴于您的查询结果,可以安全地假设您的值都没有前导空格。

标签: mysql sql trim


【解决方案1】:

另一种解决方案是使用SUBSTRING()IN 将字符串的最后一个和第一个字符与空白字符列表进行比较...

(SUBSTRING(@s,  1, 1) IN (' ', '\t', '\n', '\r') OR SUBSTRING(@s, -1, 1) IN (' ', '\t', '\n', '\r'))

...其中@s 是任何输入字符串。根据您的情况,在比较列表中添加额外的空白字符。

这里有一个简单的测试来演示该表达式如何处理各种字符串输入:

SET @s_normal = 'x';
SET @s_ws_leading = '\tx';
SET @s_ws_trailing = 'x ';
SET @s_ws_both = '\rx ';

SELECT
    NOT(SUBSTRING(@s_normal,      1, 1) IN (' ', '\t', '\n', '\r') OR SUBSTRING(@s_normal,     -1, 1) IN (' ', '\t', '\n', '\r')) test_normal      #=> 1 (PASS)
  ,    (SUBSTRING(@s_ws_leading,  1, 1) IN (' ', '\t', '\n', '\r') OR SUBSTRING(@s_ws_leading, -1, 1) IN (' ', '\t', '\n', '\r')) test_ws_leading  #=> 1 (PASS)
  ,    (SUBSTRING(@s_ws_trailing, 1, 1) IN (' ', '\t', '\n', '\r') OR SUBSTRING(@s_ws_trailing,-1, 1) IN (' ', '\t', '\n', '\r')) test_ws_trailing #=> 1 (PASS)
  ,    (SUBSTRING(@s_ws_both,     1, 1) IN (' ', '\t', '\n', '\r') OR SUBSTRING(@s_ws_both,    -1, 1) IN (' ', '\t', '\n', '\r')) test_ws_both     #=> 1 (PASS)
;

如果这是你经常要做的事情,你也可以为它创建一个函数:

DROP FUNCTION IF EXISTS has_leading_or_trailing_whitespace;

CREATE FUNCTION has_leading_or_trailing_whitespace(s VARCHAR(2000))
  RETURNS BOOLEAN
  DETERMINISTIC
RETURN (SUBSTRING(s, 1, 1) IN (' ', '\t', '\n', '\r') OR SUBSTRING(s, -1, 1) IN (' ', '\t', '\n', '\r'))
;

# test
SELECT
    NOT(has_leading_or_trailing_whitespace(@s_normal     )) #=> 1 (PASS)
  ,     has_leading_or_trailing_whitespace(@s_ws_leading )  #=> 1 (PASS)
  ,     has_leading_or_trailing_whitespace(@s_ws_trailing)  #=> 1 (PASS)
  ,     has_leading_or_trailing_whitespace(@s_ws_both    )  #=> 1 (PASS)
;

【讨论】:

    【解决方案2】:

    这是RegEx的示例

    SELECT *
    FROM 
        `foo`
    WHERE 
       (name REGEXP '(^[[:space:]]|[[:space:]]$)')
    

    【讨论】:

    • @PatrickBassut 假设 OP 中的空格表示 whitespace 而不仅仅是 U+0020,这是唯一正确的答案。
    【解决方案3】:

    The CHAR and VARCHAR Types 中所述:

    所有 MySQL 排序规则的类型都是 PADSPACE。这意味着在比较 MySQL 中的所有 CHARVARCHAR 值时,不考虑任何尾随空格。

    LIKE操作符的定义中,手册指出:

    尤其是尾随空格很重要,这对于使用= 运算符执行的CHARVARCHAR 比较而言并非如此:

    this answer中所述:

    此行为在 SQL-92 和 SQL:2008 中指定。为了比较,较短的字符串被填充到较长字符串的长度。

    来自草案(8.2 ):

    如果 X 的字符长度不等于 Y 的字符长度,则为了比较,较短的字符串被有效地替换为自身的副本,该副本已扩展到较长的长度一个或多个填充字符右侧连接的字符串,其中填充字符是根据 CS 选择的。如果 CS 具有 NO PAD 特性,则填充字符是一个依赖于实现的字符,它不同于 X 和 Y 字符集中的任何字符,其排序小于 CS 下的任何字符串。否则,填充字符是

    一种解决方案:

    SELECT * FROM Foo WHERE CHAR_LENGTH(field) != CHAR_LENGTH(TRIM(field))
    

    【讨论】:

      【解决方案4】:
      SELECT *
      FROM 
          `foo`
      WHERE 
         (name LIKE ' %')
      OR 
         (name LIKE '% ')
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-25
      • 1970-01-01
      相关资源
      最近更新 更多