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


134

我有一个包含两个字段(国家和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中的空格?


1
将我的答案添加为注释以使其更加可见:只需清楚一点,TRIM默认情况下仅删除空格(并非所有空格)。这里是DOC:dev.mysql.com/doc/refman/5.0/en/...
mulya

Answers:


270

您正在寻找TRIM

UPDATE FOO set FIELD2 = TRIM(FIELD2);

19
注意:这只会删除常规空格,不会删除其他空白字符(制表符,换行符等)
TM。

30
是的,您对的是@TM,所以最好使用:UPDATE FOO set FIELD2 = TRIM(Replace(Replace(Replace(FIELD2,'\ t',''),'\ n',''),'\ r' ,'')); 等等
克里斯·辛

9
尽管@ChrisSim的解决方案也将在内容内替换换行符和选项卡-当然,这可能不是大多数人想要的TRIM功能!
JoLoCo

41

我从您的答案和其他链接中得出的一个普遍答案对我有用,我在评论中写道:

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

等等

因为trim()不会删除所有空白,所以最好替换掉您想要的所有空白,而不是对其进行修剪。

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


7
这将删除所有选项卡/换行符。TRIM仅应删除字符串两端的空格。
DisgruntledGoat 2014年

1
这是一个思考和删除换行符的好主意,谢谢,工作就像一种魅力,我对此表示赞同,bcoz对于这种思考@Chris Sim
Sankar Ganesh

25

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

选择查询时修剪不起作用

这有效

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

虽然这不是

select trim(name) from test;

9
TRIM()在一份SELECT声明中对我来说效果很好,我真的很好奇为什么这个答案获得了如此多的支持。您正在使用mysql吗?什么版本的?
billynoah


11
是的,这个答案是错误的。这是如何获得50多个投票的?
Loko

5
这不仅是错误的,而且很危险。它会严重破坏某人的数据。
某些非描述用户,

1
我投票了。测试用例:SELECT CONCAT('"', TRIM(" hello world "), '"') AS `trimmed value` FROM DUAL给出所需的输出"hello world"。尽管replace变量危险地删除了空格作为单词分隔符:SELECT CONCAT('"', REPLACE(" hello world ", ' ', '')) AS `replaced value` FROM DUAL 提供了不必要的输出"helloworld"
Piemol


11

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

如其他文章所述,默认值TRIM仅删除空格-而不是制表符,换页符等TRIM。指定其他空格字符的s 组合可能会提供有限的改进,例如TRIM(BOTH '\r' FROM TRIM(BOTH '\n' FROM TRIM(BOTH '\f' FROM TRIM(BOTH '\t' FROM TRIM(txt)))))。但是这种方法的问题是只能为一个特定TRIM的字符指定一个字符,而这些字符只能从开头和结尾删除。因此,如果要修剪的字符串类似\t \t \t \t(例如,空格和制表符),则TRIM需要更多s-在一般情况下,它可能会无限期地继续下去。

对于轻量级解决方案,应该有可能编写一个简单的用户定义函数(UDF),以通过遍历字符串开头和结尾的字符来完成这项工作。但是我不打算这样做...因为我已经写了一个重量更重的正则表达式替换器,它也可以完成这项工作-并且可能由于其他原因而有用,如本博客文章中所述

演示版

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

功能

-- ------------------------------------------------------------------------------------
-- 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;

4

该语句将删除并更新数据库的字段内容

删除字段值左侧的空格

更新表SET field1 = LTRIM(field1);

例如 UPDATE成员SET firstName = LTRIM(firstName);

删除字段值右侧的空格

更新表SETfield1 = RTRIM(field1);

例如 UPDATE成员SET firstName = RTRIM(firstName);


2

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

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

要么

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

要么

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

请注意,FIELD的第一个实例用单引号引起来,而第二个实例根本没有用引号引起来。我必须这样做,否则给我一个语法错误,说当我用双引号引起来时它是重复的主键。


1

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

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

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


0

您可以使用ltrim或rtrim清除左右或字符串的空格。


0

您可以使用以下sql,UPDATE TABLE SET Column= replace(Column,'','')


-5

我知道它已经被接受了,但是对于像我这样的人来说,他们寻求“删除所有空格”(不仅仅是在字符串的开头和结尾):

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

编辑2019/6/20:是的,这不好。从“第一次出现字符空间时”开始,函数将返回字符串的一部分。因此,我猜想这将删除开头和结尾的空格并返回第一个单词:

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

5
这与OP无关。
mickmackusa 2014年

4
哇,您并没有删除所有空格 -您正在删除从第一个空格开始的所有内容
Timo
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.