Como remover espaços em branco à esquerda e à direita em um campo MySQL?

134

Eu tenho uma tabela com dois campos (países e códigos ISO):

Table1

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

Em algumas linhas, o segundo campo possui espaços em branco no início e / ou no final, o que está afetando as consultas.

Table1

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

Existe uma maneira (no SQL) de percorrer a tabela e encontrar / substituir o espaço em branco no campo2?

KB.
fonte
1
Adicionando minha resposta como comentário para torná-la mais visível: Para ficar claro, o TRIM, por padrão, remove apenas os espaços (nem todos os espaços em branco). Aqui está o documento: dev.mysql.com/doc/refman/5.0/en/…
mulya

Respostas:

270

Você está procurando TRIM .

UPDATE FOO set FIELD2 = TRIM(FIELD2);
cwallenpoole
fonte
19
Nota: isso remove apenas espaços regulares e não outros caracteres de espaço em branco (tabulação, nova linha etc.)
TM.
30
sim você está certo @TM, portanto, é melhor usar: UPDATE FOO set FIELD2 = TRIM (Replace (Replace (Replace (Replace (FIELD2, '\ t', ''), '\ n', ''), '\ r' , '')); etc.
Chris Sim
9
Embora a solução do @ ChrisSim substitua novas linhas e guias dentro do conteúdo também, é claro - o que provavelmente não é o que a maioria das pessoas deseja de uma função TRIM!
JoLoCo
41

Uma resposta geral que eu compus a partir de suas respostas e de outros links e funcionou para mim e escrevi em um comentário é:

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

etc.

Como o trim () não remove todos os espaços em branco, é melhor substituir todos os espaços em branco que você deseja e do que apará-los.

Espero poder ajudá-lo a compartilhar minha resposta :)

Chris Sim
fonte
7
Isso remove todas as guias / novas linhas. O TRIM deve remover apenas os espaços em branco em cada extremidade da cadeia.
usar o seguinte
1
esta uma boa idéia de pensar e removendo os novos caracteres de linha, graças, funciona como um encanto, eu tenho upvoted-lo, bcoz para este pensamento @ Chris Sim
Sankar Ganesh
25

Por favor, entenda o caso de uso antes de usar esta solução:

aparar não funciona durante a consulta de seleção

Isso funciona

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

Enquanto isso não

select trim(name) from test;
amitchhajer
fonte
9
TRIM()funciona bem para mim em uma SELECTdeclaração, estou realmente curioso para saber por que essa resposta tem tantos votos positivos. Você está usando mysql? Qual versão?
Billynoah 16/05
1
remove guarnição esquerda e à direita espaços única dev.mysql.com/doc/refman/5.7/en/string-functions.html
amitchhajer
11
Sim, esta resposta está errada. Como isso conseguiu mais de 50 votos positivos?
Loko
5
Isso não é apenas errado, é perigoso. Ele pode distorcer seriamente os dados de alguém.
some-não descrita pelo usuário
1
Eu voto negativo. Testcase: SELECT CONCAT('"', TRIM(" hello world "), '"') AS `trimmed value` FROM DUALfornece a saída desejada "hello world". Enquanto a variante de substituição remove perigosamente o espaço como separador de palavras: SELECT CONCAT('"', REPLACE(" hello world ", ' ', '')) AS `replaced value` FROM DUAL fornece a saída indesejada"helloworld"
Piemol
11

Parece que nenhuma das respostas atuais removerá 100% do espaço em branco do início e do fim de uma string.

Como mencionado em outras postagens, o padrão TRIMapenas remove espaços - não guias, formulários etc. Uma combinação de TRIMs especificando outros caracteres de espaço em branco pode fornecer uma melhoria limitada, por exemplo TRIM(BOTH '\r' FROM TRIM(BOTH '\n' FROM TRIM(BOTH '\f' FROM TRIM(BOTH '\t' FROM TRIM(txt))))). Mas o problema dessa abordagem é que apenas um caractere pode ser especificado para um determinado TRIMe esses caracteres são removidos apenas do início e do fim. Portanto, se a string que está sendo cortada for algo como \t \t \t \t(ou seja, espaços alternativos e caracteres de tabulação), mais TRIMs seriam necessários - e, no caso geral, isso pode continuar indefinidamente.

Para uma solução leve, deve ser possível escrever uma UDF (Função Definida pelo Usuário) simples para executar o trabalho fazendo um loop entre os caracteres no início e no final de uma sequência. Mas não vou fazer isso ... como já escrevi um substituto de expressão regular um pouco mais pesado, que também pode fazer o trabalho - e pode ser útil por outros motivos, conforme descrito nesta postagem do blog .

Demo

Demonstração online do Rextester . Em particular, a última linha mostra os outros métodos com falha, mas o método de expressão regular foi bem-sucedido.

Função :

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

Uso:

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

Esta declaração removerá e atualizará o conteúdo do campo do seu banco de dados

Para remover espaços em branco no lado esquerdo do valor do campo

Tabela UPDATE SET field1 = LTRIM (campo1);

ex. UPDATE, membro SET firstName = LTRIM (firstName);

Para remover espaços em branco no lado direito do valor do campo

Tabela UPDATE SETfield1 = RTRIM (campo1);

ex. UPDATE membro SET firstName = RTRIM (firstName);

luxknight_007
fonte
2

Eu precisava aparar os valores em uma coluna de chave primária que tinha nome e sobrenome, portanto, não queria aparar todo o espaço em branco, pois isso removeria o espaço entre o nome e o sobrenome, que eu precisava manter. O que funcionou para mim foi ...

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

ou

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

ou

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

Observe que a primeira instância do FIELD está entre aspas simples, mas a segunda não está entre aspas. Eu tive que fazer dessa maneira ou isso me deu um erro de sintaxe, dizendo que era uma chave primária duplicada quando eu tinha as aspas.

MistyDawn
fonte
1

Se você precisar usar o corte na consulta de seleção, também poderá usar expressões regulares

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

retornar linhas com campo como 'query-string'

TheSameSon
fonte
0

você pode usar ltrim ou rtrim para limpar espaços em branco para a direita ou esquerda ou uma string.

Tomer
fonte
0

Você pode usar o seguinte sql, UPDATE TABLESET Column= replace (coluna, '', '')

Optimus Prime
fonte
-5

Eu sei que já é aceito, mas para aqueles que buscam "remover TODOS os espaços em branco" (não apenas no início e no final da string):

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

EDIT 2019/6/20: Sim, isso não é bom. A função retorna a parte da sequência desde "quando o espaço de caracteres ocorreu pela primeira vez". Então, acho que dizer isso remove os espaços em branco à esquerda e à direita e retorna a primeira palavra:

select SUBSTRING_INDEX(TRIM(' 1234 243'), ' ', 1);
François Breton
fonte
5
Isso não tem relevância para o PO.
mickmackusa
4
Whoah, você não está removendo todos os espaços em branco - você está removendo tudo do primeiro espaço em diante .
Timo