¿Cómo eliminar espacios en blanco iniciales y finales en un campo MySQL?

134

Tengo una tabla con dos campos (países y códigos ISO):

Table1

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

En algunas filas, el segundo campo tiene espacios en blanco al inicio y / o al final, lo que afecta las consultas.

Table1

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

¿Hay alguna manera (en SQL) de recorrer la tabla y encontrar / reemplazar el espacio en blanco en el campo2?

KB.
fuente
1
Agregar mi respuesta como comentario para hacerlo más visible: para ser claros, TRIM por defecto solo elimina espacios (no todos los espacios en blanco). Aquí está el doc: dev.mysql.com/doc/refman/5.0/en/...
Mulya

Respuestas:

270

Estás buscando TRIM .

UPDATE FOO set FIELD2 = TRIM(FIELD2);
cwallenpoole
fuente
19
Nota: esto solo elimina espacios regulares y no otros caracteres de espacio en blanco (tabulación, nueva línea, etc.)
TM.
30
sí, tienes razón @ TM, así que es mejor usar: ACTUALIZAR FOO set FIELD2 = TRIM (Reemplazar (Reemplazar (Reemplazar (FIELD2, '\ t', ''), '\ n', ''), '\ r' , '')); etc.
Chris Sim
9
Aunque la solución de @ ChrisSim reemplazará las nuevas líneas y pestañas DENTRO del contenido, por supuesto, ¡lo cual probablemente no sea lo que la mayoría de la gente quiere de una función TRIM!
JoLoCo
41

Una respuesta general que compuse de sus respuestas y de otros enlaces y funcionó para mí y la escribí en un comentario es:

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

etc.

Debido a que trim () no elimina todos los espacios en blanco, es mejor reemplazar todos los espacios en blanco que desee y luego recortarlo.

Espero poder ayudarte a compartir mi respuesta :)

Chris Sim
fuente
77
Esto elimina todas las pestañas / líneas nuevas. TRIM solo debe eliminar espacios en blanco en cada extremo de la cadena.
DisgruntledGoat
1
esta es una buena idea de pensar y eliminar los nuevos caracteres de la línea, gracias, funciona como un encanto, lo he votado, porque este pensamiento @Chris Sim
Sankar Ganesh
25

Comprenda el caso de uso antes de usar esta solución:

trim no funciona mientras se realiza la consulta de selección

Esto funciona

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

Si bien esto no

select trim(name) from test;
amitchhajer
fuente
9
TRIM()funciona bien para mí en una SELECTdeclaración, tengo mucha curiosidad sobre por qué esta respuesta tiene tantos votos positivos. ¿Estás usando mysql? Que versión
billynoah
1
Retire el marco espacios iniciales y finales solamente dev.mysql.com/doc/refman/5.7/en/string-functions.html
amitchhajer
11
Sí, esta respuesta es incorrecta. ¿Cómo obtuvo esto más de 50 votos a favor?
Loko
55
Esto no solo está mal, es peligroso. Puede confundir seriamente los datos de alguien.
un usuario no descripto el
1
Yo voté en contra. Testcase: SELECT CONCAT('"', TRIM(" hello world "), '"') AS `trimmed value` FROM DUALda la salida deseada "hello world". Mientras que la variante de reemplazo elimina peligrosamente el espacio como separador de palabras: SELECT CONCAT('"', REPLACE(" hello world ", ' ', '')) AS `replaced value` FROM DUAL da la salida no deseada"helloworld"
Piemol
11

Parece que ninguna de las respuestas actuales en realidad eliminará el 100% del espacio en blanco desde el inicio y el final de una cadena.

Como se mencionó en otras publicaciones, el valor predeterminado TRIMsolo elimina espacios, no pestañas, avances de formulario, etc. Una combinación de TRIMs que especifique otros caracteres de espacio en blanco puede proporcionar una mejora limitada, por ejemplo TRIM(BOTH '\r' FROM TRIM(BOTH '\n' FROM TRIM(BOTH '\f' FROM TRIM(BOTH '\t' FROM TRIM(txt))))). Pero el problema con este enfoque es que solo se puede especificar un único carácter para un particular TRIMy esos caracteres solo se eliminan desde el principio y el final. Entonces, si la cadena que se está recortando es algo así \t \t \t \t(es decir, espacios alternativos y caracteres de tabulación), TRIMse necesitarían más s, y en el caso general esto podría continuar indefinidamente.

Para una solución ligera, debería ser posible escribir una función definida por el usuario (UDF) simple para hacer el trabajo recorriendo los caracteres al principio y al final de una cadena. Pero no voy a hacer eso ... ya que he escrito un sustituto de expresiones regulares bastante más pesado que también puede hacer el trabajo, y puede ser útil por otras razones, como se describe en esta publicación de blog .

Manifestación

Demo en línea de Rextester . En particular, la última fila muestra los otros métodos que fallan pero el método de expresión regular tiene éxito.

Función :

-- ------------------------------------------------------------------------------------
-- 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
fuente
4

Esta declaración eliminará y actualizará el contenido de campo de su base de datos

Para eliminar espacios en blanco en el lado izquierdo del valor del campo

ACTUALIZAR tabla SET field1 = LTRIM (field1);

ex. ACTUALIZAR miembro SET firstName = LTRIM (firstName);

Para eliminar espacios en blanco en el lado derecho del valor del campo

ACTUALIZAR tabla SETfield1 = RTRIM (campo1);

ex. ACTUALIZAR miembro SET firstName = RTRIM (firstName);

luxknight_007
fuente
2

Necesitaba recortar los valores en una columna de clave principal que tenía nombre y apellido, por lo que no quería recortar todo el espacio en blanco, ya que eso eliminaría el espacio entre el nombre y el apellido, que tenía que mantener. Lo que funcionó para mí fue ...

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

o

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

o

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

Tenga en cuenta que la primera instancia de FIELD está entre comillas simples, pero la segunda no está entre comillas. Tuve que hacerlo de esta manera o me dio un error de sintaxis que decía que era una clave primaria duplicada cuando tenía ambas entre comillas.

MistyDawn
fuente
1

Si necesita usar recortar en la consulta de selección, también puede usar expresiones regulares

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

devolver filas con un campo como 'query-string'

TheSameSon
fuente
0

puede usar ltrim o rtrim para limpiar espacios en blanco a la derecha o izquierda o una cadena.

Tomer
fuente
0

Puede usar el siguiente sql, UPDATE TABLESET Column= replace (Column, '', '')

Optimus Prime
fuente
-5

Sé que ya está aceptado, pero para aquellos como yo que buscan "eliminar TODOS los espacios en blanco" (no solo al principio y al final de la cadena):

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

EDITAR 2019/6/20: Sí, eso no es bueno. La función devuelve la parte de la cadena desde "cuando se produjo el espacio de caracteres por primera vez". Entonces, supongo que decir esto elimina los espacios en blanco iniciales y finales y devuelve la primera palabra:

select SUBSTRING_INDEX(TRIM(' 1234 243'), ' ', 1);
François Breton
fuente
55
Esto no tiene relevancia para el OP.
mickmackusa
44
Whoah, no estás eliminando todos los espacios en blanco , estás eliminando todo desde el primer espacio en adelante .
Timo