MySQL选择包含前导或尾随空格的字段

时间:2013-05-23 21:55:52

标签: mysql sql trim

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

UPDATE Foo SET field = TRIM(field);

我想在运行之前看到这些影响的字段。我尝试了这个,但返回0结果:

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

似乎这应该有效,但事实并非如此。

有人有解决方案吗?此外,好奇为什么这不起作用......

4 个答案:

答案 0 :(得分:46)

正如The CHAR and VARCHAR Types所述:

  

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

LIKE运算符的定义中,手册指出:

  

特别是,尾随空格很重要,但对于CHAR运算符执行的VARCHAR=比较则不然:

this answer中所述:

  

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

     

从草案(8.2<比较谓词>):

     
    

如果X的字符长度不等于Y的字符长度,那么为了比较的目的,较短的字符串被有效地替换为已经延长到较长的长度的自身的副本。字符串通过串联在一个或多个填充字符的右侧,其中填充字符是基于CS选择的。如果CS具有NO PAD特性,则填充字符是与实现有关的字符,不同于X和Y字符集中的任何字符,其整理的字符串少于CS下的任何字符串。否则,填充字符是< space>。

  

一个解决方案:

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

答案 1 :(得分:29)

SELECT *
FROM 
    `foo`
WHERE 
   (name LIKE ' %')
OR 
   (name LIKE '% ')

答案 2 :(得分:1)

以下是RegEx

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

答案 3 :(得分:0)

另一种解决方案可能是使用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)
;