我可以使用MySQL TRIM()
方法清除包含带UPDATE
的前导或尾随空格的字段,如下所示:
UPDATE Foo SET field = TRIM(field);
我想在运行之前看到这些影响的字段。我尝试了这个,但返回0结果:
SELECT * FROM Foo WHERE field != TRIM(field);
似乎这应该有效,但事实并非如此。
有人有解决方案吗?此外,好奇为什么这不起作用......
答案 0 :(得分:46)
正如The CHAR
and VARCHAR
Types所述:
所有MySQL排序规则都是
PADSPACE
类型。这意味着MySQL中的所有CHAR
和VARCHAR
值都会进行比较,而不考虑任何尾随空格。
在LIKE
运算符的定义中,手册指出:
如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)
;