33

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

UPDATE Foo SET field = TRIM(field);

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

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

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

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

4

4 回答 4

59

TheCHARVARCHARTypes下所述:

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

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

特别是,尾随空格很重要,对于使用运算符执行的比较CHARVARCHAR比较而言,这是不正确的=

本答案所述:

此行为在 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))
于 2013-05-23T22:02:13.010 回答
36
SELECT *
FROM 
    `foo`
WHERE 
   (name LIKE ' %')
OR 
   (name LIKE '% ')
于 2013-05-23T21:59:21.057 回答
7

这是正则表达式的示例

SELECT *
FROM 
    `foo`
WHERE 
   (name REGEXP '(^[[:space:]]|[[:space:]]$)')
于 2019-02-20T22:54:32.873 回答
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)
;
于 2020-08-13T19:38:42.570 回答