简体   繁体   English

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

[英]How to remove leading and trailing whitespace in a MySQL field?

I have a table with two fields (countries and ISO codes):我有一个包含两个字段(国家和 ISO 代码)的表:

Table1

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

In some rows the second field has whitespace at the start and/or end, which is affecting queries.在某些行中,第二个字段在开头和/或结尾处有空格,这会影响查询。

Table1

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

Is there a way (in SQL) to go through the table and find/replace the whitespace in field2?有没有办法(在 SQL 中)遍历表并查找/替换 field2 中的空格?

You're looking for TRIM .您正在寻找TRIM

UPDATE FOO set FIELD2 = TRIM(FIELD2);

Seems like it might be worth it to mention that TRIM can support multiple types of whitespace, but only one at a time and it will use a space by default.似乎值得一提的是,TRIM 可以支持多种类型的空格,但一次只能支持一种,并且默认情况下会使用一个空格。 You can, however, nest TRIM s.但是,您可以嵌套TRIM

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

If you really want to get rid of all the whitespace in one call, you're better off using REGEXP_REPLACE along with the [[:space:]] notation.如果您真的想在一次调用中去掉所有空格,最好使用REGEXP_REPLACE[[:space:]]表示法。 Here is an example:下面是一个例子:

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+

A general answer that I composed from your answers and from other links and it worked for me and I wrote it in a comment is:我根据您的答案和其他链接组成的一般答案对我有用,我在评论中写道:

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

etc.等等。

Because trim() doesn't remove all the white spaces so it's better to replace all the white spaces u want and than trim it.因为 trim() 不会删除所有空格,所以最好替换你想要的所有空格而不是修剪它。

Hope I could help you with sharing my answer :)希望我能帮助你分享我的答案:)

Please understand the use case before using this solution:请在使用此解决方案之前了解用例:

trim does not work while doing select query执行选择查询时修剪不起作用

This works这有效

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

While this doesn't虽然这不

select trim(name) from test;

Just to be clear, TRIM by default only remove spaces (not all whitespaces).需要明确的是,默认情况下 TRIM仅删除空格(并非所有空格)。 Here is the doc: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_trim这是文档: http : //dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_trim

It seems none of the current answers will actually remove 100% of whitespace from the start and end of a string.似乎当前的答案都不会真正从字符串的开头和结尾删除 100% 的空格。

As mentioned in other posts, the default TRIM only removes spaces - not tabs, formfeeds etc. A combination of TRIM s specifying other whitespace characters may provide a limited improvement eg TRIM(BOTH '\\r' FROM TRIM(BOTH '\\n' FROM TRIM(BOTH '\\f' FROM TRIM(BOTH '\\t' FROM TRIM(txt))))) .正如其他帖子中提到的,默认TRIM仅删除空格 - 而不是制表符、换页符等。 指定其他空白字符的TRIM组合可能提供有限的改进,例如TRIM(BOTH '\\r' FROM TRIM(BOTH '\\n' FROM TRIM(BOTH '\\f' FROM TRIM(BOTH '\\t' FROM TRIM(txt))))) But the problem with this approach is only a single character can be specified for a particular TRIM and those characters are only removed from the start and end.但是这种方法的问题是只能为特定TRIM指定单个字符,并且这些字符仅从开头和结尾删除。 So if the string being trimmed is something like \\t \\t \\t \\t (ie alternate spaces and tab characters), more TRIM s would be needed - and in the general case this could go on indefinitely.因此,如果要修剪的字符串类似于\\t \\t \\t \\t (即备用空格和制表符),则需要更多TRIM s - 在一般情况下,这可能会无限期地持续下去。

For a lightweight solution, it should be possible to write a simple User Defined Function (UDF) to do the job by looping through the characters at the start and end of a string.对于轻量级解决方案,应该可以编写一个简单的用户定义函数 (UDF) 来通过循环字符串开头和结尾的字符来完成这项工作。 But I'm not going to do that... as I've already written a rather more heavyweight regular expression replacer which can also do the job - and may come in useful for other reasons, as described in this blog post .但我不会那样做……因为我已经写了一个更重量级的正则表达式替换器,它也可以完成这项工作 - 并且可能由于其他原因而有用,如本博文所述。

Demo演示

Rextester online demo . Rexester 在线演示 In particular, the last row shows the other methods failing but the regular expression method succeeding.特别是,最后一行显示其他方法失败但正则表达式方法成功。

Function :功能

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

Usage:用法:

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

This statement will remove and update the field content of your database此语句将删除和更新数据库的字段内容

To remove whitespaces in the left side of the field value删除字段值左侧的空格

UPDATE table SET field1 = LTRIM(field1);更新表 SET field1 = LTRIM(field1);

ex.前任。 UPDATE member SET firstName = LTRIM(firstName);更新成员 SET firstName = LTRIM(firstName);

To remove whitespaces in the right side of the field value删除字段值右侧的空格

UPDATE table SETfield1 = RTRIM(field1);更新表 SETfield1 = RTRIM(field1);

ex.前任。 UPDATE member SET firstName = RTRIM(firstName);更新成员 SET firstName = RTRIM(firstName);

I needed to trim the values in a primary key column that had first and last names, so I did not want to trim all white space as that would remove the space between the first and last name, which I needed to keep.我需要修剪具有名字和姓氏的主键列中的值,所以我不想修剪所有空格,因为这会删除我需要保留的名字和姓氏之间的空格。 What worked for me was...对我有用的是...

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

or要么

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

or要么

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

Note that the first instance of FIELD is in single quotes but the second is not in quotes at all.请注意, FIELD 的第一个实例在单引号中,但第二个实例根本不在引号中。 I had to do it this way or it gave me a syntax error saying it was a duplicate primary key when I had both in quotes.我必须这样做,否则它给了我一个语法错误,说当我在引号中时,它是一个重复的主键。

If you need to use trim in select query, you can also use regular expressions如果需要在select查询中使用trim,也可以使用正则表达式

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

return rows with field like ' query-string '返回带有“查询字符串”等字段的行

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

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

I know its already accepted, but for thoses like me who look for "remove ALL whitespaces" (not just at the begining and endingof the string):我知道它已经被接受了,但是对于像我这样寻找“删除所有空格”的人(不仅仅是在字符串的开头和结尾):

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

EDIT 2019/6/20 : Yeah, that's not good.编辑 2019/6/20:是的,那不好。 The function returns the part of the string since "when the character space occured for the first time".该函数返回字符串的一部分,因为“当字符空间第一次出现时”。 So, I guess that saying this remove the leading and trailling whitespaces and returns the first word :所以,我想说这会删除前导和尾随空格并返回第一个单词:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM