我可以使用 MySQLTRIM()
方法来清理包含前导或尾随空格的字段,UPDATE
如下所示:
UPDATE Foo SET field = TRIM(field);
我想在运行之前实际查看这将影响的字段。我试过了,但返回 0 个结果:
SELECT * FROM Foo WHERE field != TRIM(field);
似乎这应该有效,但事实并非如此。
有人有解决方案吗?另外,很好奇为什么这不起作用......
如TheCHAR
和VARCHAR
Types下所述:
所有 MySQL 排序规则都是 type
PADSPACE
。这意味着在比较 MySQL 中的所有CHAR
和VARCHAR
值时,不考虑任何尾随空格。
在LIKE
操作员的定义中,手册指出:
如本答案所述:
此行为在 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))
SELECT *
FROM
`foo`
WHERE
(name LIKE ' %')
OR
(name LIKE '% ')
这是正则表达式的示例
SELECT *
FROM
`foo`
WHERE
(name REGEXP '(^[[:space:]]|[[:space:]]$)')
另一种解决方案可能是使用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)
;