Comment supprimer les espaces de début et de fin dans un champ MySQL?

134

J'ai une table avec deux champs (pays et codes ISO):

Table1

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

Dans certaines lignes, le deuxième champ contient des espaces au début et / ou à la fin, ce qui affecte les requêtes.

Table1

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

Existe-t-il un moyen (en SQL) de parcourir la table et de trouver / remplacer l'espace blanc dans field2?

KB.
la source
1
Ajouter ma réponse en commentaire pour la rendre plus visible: Juste pour être clair, TRIM par défaut ne supprime que les espaces (pas tous les espaces). Voici le doc: dev.mysql.com/doc/refman/5.0/en/…
mulya

Réponses:

270

Vous recherchez TRIM .

UPDATE FOO set FIELD2 = TRIM(FIELD2);
cwallenpoole
la source
19
Remarque: cela supprime uniquement les espaces normaux et pas les autres caractères d'espacement (tabulation, nouvelle ligne, etc.)
TM.
30
oui vous avez raison @TM donc il vaut mieux utiliser: UPDATE FOO set FIELD2 = TRIM (Replace (Replace (Replace (FIELD2, '\ t', ''), '\ n', ''), '\ r' , '')); etc.
Chris Sim
9
Bien que la solution de @ ChrisSim remplacera également les nouvelles lignes et les onglets DANS le contenu, bien sûr - ce qui n'est probablement pas ce que la plupart des gens attendent d'une fonction TRIM!
JoLoCo
41

Une réponse générale que j'ai composée à partir de vos réponses et d'autres liens et cela a fonctionné pour moi et je l'ai écrite dans un commentaire est:

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

etc.

Parce que trim () ne supprime pas tous les espaces blancs, il est donc préférable de remplacer tous les espaces blancs que vous voulez et de les couper.

J'espère que je pourrais vous aider à partager ma réponse :)

Chris Sim
la source
7
Cela supprime tous les onglets / nouvelles lignes. TRIM ne doit supprimer que les espaces à chaque extrémité de la chaîne.
DisgruntledGoat
1
c'est une bonne idée de penser et de supprimer les nouveaux caractères de la ligne, merci, fonctionne comme un charme, je l'ai voté pour cette réflexion @Chris Sim
Sankar Ganesh
25

Veuillez comprendre le cas d'utilisation avant d'utiliser cette solution:

le découpage ne fonctionne pas lors de l'exécution de la requête de sélection

Cela marche

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

Bien que ce ne soit pas

select trim(name) from test;
amitchhajer
la source
9
TRIM()fonctionne bien pour moi dans une SELECTdéclaration, je suis vraiment curieux de savoir pourquoi cette réponse a reçu autant de votes positifs. Utilisez-vous mysql? Quelle version?
billynoah
1
trim supprime uniquement les espaces de début
amitchhajer
11
Ouais, cette réponse est fausse. Comment cela a-t-il obtenu plus de 50 votes positifs?
Loko
5
Ce n'est pas seulement faux, c'est dangereux. Cela peut gravement brouiller les données de quelqu'un.
some-non-descript-user
1
J'ai voté contre. Testcase: SELECT CONCAT('"', TRIM(" hello world "), '"') AS `trimmed value` FROM DUALdonne la sortie souhaitée "hello world". Alors que la variante de remplacement supprime dangereusement l'espace comme séparateur de mots: SELECT CONCAT('"', REPLACE(" hello world ", ' ', '')) AS `replaced value` FROM DUAL donne la sortie indésirable"helloworld"
Piemol
11

Il semble qu'aucune des réponses actuelles ne supprime réellement 100% des espaces du début et de la fin d'une chaîne.

Comme mentionné dans d'autres articles, la valeur par défaut TRIMne supprime que les espaces - pas les tabulations, les sauts de formulaire, etc. Une combinaison de TRIMs spécifiant d'autres caractères d' espacement peut fournir une amélioration limitée, par exemple TRIM(BOTH '\r' FROM TRIM(BOTH '\n' FROM TRIM(BOTH '\f' FROM TRIM(BOTH '\t' FROM TRIM(txt))))). Mais le problème avec cette approche est qu'un seul caractère peut être spécifié pour un particulier TRIMet que ces caractères ne sont supprimés que du début et de la fin. Donc, si la chaîne à couper est quelque chose comme \t \t \t \t(c'est-à-dire des espaces et des tabulations alternés), plus de TRIMs seraient nécessaires - et dans le cas général, cela pourrait durer indéfiniment.

Pour une solution légère, il devrait être possible d'écrire une simple fonction définie par l'utilisateur (UDF) pour faire le travail en boucle sur les caractères au début et à la fin d'une chaîne. Mais je ne vais pas le faire ... car j'ai déjà écrit un remplaçant d'expressions régulières plutôt plus lourd qui peut également faire le travail - et peut être utile pour d'autres raisons, comme décrit dans ce billet de blog .

Démo

Démo en ligne de Rextester . En particulier, la dernière ligne montre les autres méthodes échouant mais la méthode d'expression régulière réussissant.

Fonction :

-- ------------------------------------------------------------------------------------
-- 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;
Steve Chambers
la source
4

Cette déclaration supprimera et mettra à jour le contenu du champ de votre base de données

Pour supprimer les espaces dans la partie gauche de la valeur du champ

UPDATE table SET field1 = LTRIM (field1);

ex. UPDATE membre SET firstName = LTRIM (firstName);

Pour supprimer les espaces dans la partie droite de la valeur du champ

UPDATE table SETfield1 = RTRIM (champ1);

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

luxknight_007
la source
2

J'avais besoin de rogner les valeurs dans une colonne de clé primaire contenant le prénom et le nom, je ne voulais donc pas rogner tout l'espace blanc car cela supprimerait l'espace entre le prénom et le nom, que je devais conserver. Ce qui a fonctionné pour moi était ...

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

ou

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

ou

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

Notez que la première instance de FIELD est entre guillemets simples mais la seconde n'est pas du tout entre guillemets. J'ai dû le faire de cette façon ou cela m'a donné une erreur de syntaxe disant que c'était une clé primaire en double alors que j'avais les deux entre guillemets.

MistyDawn
la source
1

Si vous devez utiliser trim dans la requête de sélection, vous pouvez également utiliser des expressions régulières

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

renvoie les lignes avec un champ comme 'query-string'

TheSameSon
la source
0

vous pouvez utiliser ltrim ou rtrim pour nettoyer les espaces pour la droite ou la gauche ou une chaîne.

Tomer
la source
0

Vous pouvez utiliser le sql suivant, UPDATE TABLESET Column= replace (Column, '', '')

Optimus Prime
la source
-5

Je sais que c'est déjà accepté, mais pour ceux comme moi qui recherchent "supprimer TOUS les espaces" (pas seulement au début et à la fin de la chaîne):

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

EDIT 2019/6/20: Ouais, ce n'est pas bon. La fonction retourne la partie de la chaîne depuis "quand l'espace de caractères s'est produit pour la première fois". Donc, je suppose que dire cela supprime les espaces blancs de début et de fin et renvoie le premier mot:

select SUBSTRING_INDEX(TRIM(' 1234 243'), ' ', 1);
François Breton
la source
5
Cela n'a aucun rapport avec le PO.
mickmackusa
4
Whoah, vous ne supprimez pas tous les espaces - vous supprimez tout à partir du premier espace .
Timo