如何删除 MySQL 字段中的前导空格和尾随空格?

我有一个包含两个字段(国家和 ISO 代码)的表:

Table1


field1 - e.g. 'Afghanistan' (without quotes)
field2 - e.g. 'AF'(without quotes)

在一些行中,第二个字段在开始和/或结束处有空格,这会影响查询。

Table1


field1 - e.g. 'Afghanistan' (without quotes)
field2 - e.g. ' AF' (without quotes but with that space in front)

有没有办法(在 SQL 中)遍历表并查找/替换 field2中的空格?

284116 次浏览

你在找 TRIM

UPDATE FOO set FIELD2 = TRIM(FIELD2);

似乎值得一提的是 TRIM 可以支持多种类型的空格,但一次只能使用一种,并且默认使用空格。但是,您可以嵌套 TRIM

 TRIM(BOTH ' ' FROM TRIM(BOTH '\n' FROM column))

如果您真的想在一次调用中去掉 所有的空格,那么最好使用 REGEXP_REPLACE[[:space:]]符号。这里有一个例子:

SELECT
-- using concat to show that the whitespace is actually removed.
CONCAT(
'+',
REGEXP_REPLACE(
'    ha ppy    ',
-- This regexp matches 1 or more spaces at the beginning with ^[[:space:]]+
-- And 1 or more spaces at the end with [[:space:]]+$
-- By grouping them with `()` and splitting them with the `|`
-- we match all of the expected values.
'(^[[:space:]]+|[[:space:]]+$)',


-- Replace the above with nothing
''
),
'+')
as my_example;
-- outputs +ha ppy+

在使用此解决方案之前,请了解用例:

在执行选择查询时,装饰不起作用

这个管用

select replace(name , ' ','') from test;

而这个不是

select trim(name) from test;

需要说明的是,默认情况下 TRIM 是 只删除空格(不是所有的空格)

我知道它已经被接受了,但是对于那些像我一样寻找“删除所有空格”(不仅仅是字符串的开始和结束)的人:

select SUBSTRING_INDEX('1234 243', ' ', 1);
// returns '1234'

2019年6月20日编辑: 是的,情况不妙。该函数返回自“当字符空间第一次出现时”以来的字符串部分。 因此,我猜这样做会去掉前面和后面的空格,并返回第一个单词:

select SUBSTRING_INDEX(TRIM(' 1234 243'), ' ', 1);

您可以使用 lrim 或 rrim 来清除右边、左边或字符串的空白。

此语句将删除和更新数据库的字段内容

移除字段值左侧的空白

更新表 SET field1 = LTRIM (field1) ;

更新成员 SET firstName = LTRIM (firstName) ;

删除字段值右侧的空白

更新表 SETfield1 = RTRIM (field1) ;

更新成员 SET firstName = RTRIM (firstName) ;

如果需要在选择查询中使用修剪,也可以使用正则表达式

SELECT * FROM table_name WHERE field RLIKE ' * query-string *'

返回带有“ query-string”字段的行

我从你们的回答和其他链接中总结出来的一个普遍的答案,对我很有用,我在评论中写道:

 UPDATE FOO set FIELD2 = TRIM(Replace(Replace(Replace(FIELD2,'\t',''),'\n',''),'\r',''));

等等。

因为镶边()不会移除所有的空白,所以最好替换所有你想要的空白,而不是修剪它。

希望我能帮助你分享我的答案:)

似乎没有一个当前的答案实际上会从字符串的开头和结尾删除100% 的空格。

正如在其他文章中提到的,默认的 TRIM只删除空格——而不是制表符、 formfeed 等。指定其他空格字符的 TRIM组合可能提供有限的改进,例如 TRIM(BOTH '\r' FROM TRIM(BOTH '\n' FROM TRIM(BOTH '\f' FROM TRIM(BOTH '\t' FROM TRIM(txt)))))。但是这种方法的问题在于只能为特定的 TRIM指定一个字符,并且只能从开始和结束处删除这些字符。因此,如果被修剪的字符串类似于 \t \t \t \t(即替换空格和制表符) ,那么将需要更多的 TRIM——在一般情况下,这可能会无限期地继续下去。

对于轻量级解决方案,应该可以编写一个简单的用户定义函数(UDF) ,通过循环遍历字符串开始和结束处的字符来完成这项工作。但我不打算这样做... 因为我已经写了一个相当重量级的 正则表达式替换程序也可以做这项工作-可能会有用的其他原因,如 这篇博文所述。

演示

特别是,最后一行显示其他方法失败,但正则表达式方法成功。

功能 :

-- ------------------------------------------------------------------------------------
-- USAGE
-- ------------------------------------------------------------------------------------
-- SELECT reg_replace(<subject>,
--                    <pattern>,
--                    <replacement>,
--                    <greedy>,
--                    <minMatchLen>,
--                    <maxMatchLen>);
-- where:
-- <subject> is the string to look in for doing the replacements
-- <pattern> is the regular expression to match against
-- <replacement> is the replacement string
-- <greedy> is TRUE for greedy matching or FALSE for non-greedy matching
-- <minMatchLen> specifies the minimum match length
-- <maxMatchLen> specifies the maximum match length
-- (minMatchLen and maxMatchLen are used to improve efficiency but are
--  optional and can be set to 0 or NULL if not known/required)
-- Example:
-- SELECT reg_replace(txt, '^[Tt][^ ]* ', 'a', TRUE, 2, 0) FROM tbl;
DROP FUNCTION IF EXISTS reg_replace;
CREATE FUNCTION reg_replace(subject VARCHAR(21845), pattern VARCHAR(21845),
replacement VARCHAR(21845), greedy BOOLEAN, minMatchLen INT, maxMatchLen INT)
RETURNS VARCHAR(21845) DETERMINISTIC BEGIN
DECLARE result, subStr, usePattern VARCHAR(21845);
DECLARE startPos, prevStartPos, startInc, len, lenInc INT;
IF subject REGEXP pattern THEN
SET result = '';
-- Sanitize input parameter values
SET minMatchLen = IF(minMatchLen < 1, 1, minMatchLen);
SET maxMatchLen = IF(maxMatchLen < 1 OR maxMatchLen > CHAR_LENGTH(subject),
CHAR_LENGTH(subject), maxMatchLen);
-- Set the pattern to use to match an entire string rather than part of a string
SET usePattern = IF (LEFT(pattern, 1) = '^', pattern, CONCAT('^', pattern));
SET usePattern = IF (RIGHT(pattern, 1) = '$', usePattern, CONCAT(usePattern, '$'));
-- Set start position to 1 if pattern starts with ^ or doesn't end with $.
IF LEFT(pattern, 1) = '^' OR RIGHT(pattern, 1) <> '$' THEN
SET startPos = 1, startInc = 1;
-- Otherwise (i.e. pattern ends with $ but doesn't start with ^): Set start position
-- to the min or max match length from the end (depending on "greedy" flag).
ELSEIF greedy THEN
SET startPos = CHAR_LENGTH(subject) - maxMatchLen + 1, startInc = 1;
ELSE
SET startPos = CHAR_LENGTH(subject) - minMatchLen + 1, startInc = -1;
END IF;
WHILE startPos >= 1 AND startPos <= CHAR_LENGTH(subject)
AND startPos + minMatchLen - 1 <= CHAR_LENGTH(subject)
AND !(LEFT(pattern, 1) = '^' AND startPos <> 1)
AND !(RIGHT(pattern, 1) = '$'
AND startPos + maxMatchLen - 1 < CHAR_LENGTH(subject)) DO
-- Set start length to maximum if matching greedily or pattern ends with $.
-- Otherwise set starting length to the minimum match length.
IF greedy OR RIGHT(pattern, 1) = '$' THEN
SET len = LEAST(CHAR_LENGTH(subject) - startPos + 1, maxMatchLen), lenInc = -1;
ELSE
SET len = minMatchLen, lenInc = 1;
END IF;
SET prevStartPos = startPos;
lenLoop: WHILE len >= 1 AND len <= maxMatchLen
AND startPos + len - 1 <= CHAR_LENGTH(subject)
AND !(RIGHT(pattern, 1) = '$'
AND startPos + len - 1 <> CHAR_LENGTH(subject)) DO
SET subStr = SUBSTRING(subject, startPos, len);
IF subStr REGEXP usePattern THEN
SET result = IF(startInc = 1,
CONCAT(result, replacement), CONCAT(replacement, result));
SET startPos = startPos + startInc * len;
LEAVE lenLoop;
END IF;
SET len = len + lenInc;
END WHILE;
IF (startPos = prevStartPos) THEN
SET result = IF(startInc = 1, CONCAT(result, SUBSTRING(subject, startPos, 1)),
CONCAT(SUBSTRING(subject, startPos, 1), result));
SET startPos = startPos + startInc;
END IF;
END WHILE;
IF startInc = 1 AND startPos <= CHAR_LENGTH(subject) THEN
SET result = CONCAT(result, RIGHT(subject, CHAR_LENGTH(subject) + 1 - startPos));
ELSEIF startInc = -1 AND startPos >= 1 THEN
SET result = CONCAT(LEFT(subject, startPos), result);
END IF;
ELSE
SET result = subject;
END IF;
RETURN result;
END;


DROP FUNCTION IF EXISTS format_result;
CREATE FUNCTION format_result(result VARCHAR(21845))
RETURNS VARCHAR(21845) DETERMINISTIC BEGIN
RETURN CONCAT(CONCAT('|', REPLACE(REPLACE(REPLACE(REPLACE(result, '\t', '\\t'), CHAR(12), '\\f'), '\r', '\\r'), '\n', '\\n')), '|');
END;


DROP TABLE IF EXISTS tbl;
CREATE TABLE tbl
AS
SELECT 'Afghanistan' AS txt
UNION ALL
SELECT ' AF' AS txt
UNION ALL
SELECT ' Cayman Islands  ' AS txt
UNION ALL
SELECT CONCAT(CONCAT(CONCAT('\t \t ', CHAR(12)), ' \r\n\t British Virgin Islands \t \t  ', CHAR(12)), ' \r\n') AS txt;


SELECT format_result(txt) AS txt,
format_result(TRIM(txt)) AS trim,
format_result(TRIM(BOTH '\r' FROM TRIM(BOTH '\n' FROM TRIM(BOTH '\f' FROM TRIM(BOTH '\t' FROM TRIM(txt))))))
AS `trim spaces, tabs, formfeeds and line endings`,
format_result(reg_replace(reg_replace(txt, '^[[:space:]]+', '', TRUE, 1, 0), '[[:space:]]+$', '', TRUE, 1, 0))
AS `reg_replace`
FROM tbl;

用法:

SELECT reg_replace(
reg_replace(txt,
'^[[:space:]]+',
'',
TRUE,
1,
0),
'[[:space:]]+$',
'',
TRUE,
1,
0) AS `trimmed txt`
FROM tbl;

我需要修剪有名和姓的主键列中的值,所以我不想修剪所有的空格,因为这样会删除名和姓之间的空格,这是我需要保留的。对我有用的是..。

UPDATE `TABLE` SET `FIELD`= TRIM(FIELD);

或者

UPDATE 'TABLE' SET 'FIELD' = RTRIM(FIELD);

或者

UPDATE 'TABLE' SET 'FIELD' = LTRIM(FIELD);

注意,FIELD 的第一个实例使用单引号,但是第二个实例根本不使用引号。我不得不这样做,否则它给我一个语法错误,说它是一个重复的主键时,我有两个引号。