Wie entferne ich führende und nachfolgende Leerzeichen in einem MySQL-Feld?

134

Ich habe eine Tabelle mit zwei Feldern (Länder und ISO-Codes):

Table1

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

In einigen Zeilen enthält das zweite Feld am Anfang und / oder Ende Leerzeichen, was sich auf Abfragen auswirkt.

Table1

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

Gibt es eine Möglichkeit (in SQL), durch die Tabelle zu gehen und das Leerzeichen in Feld2 zu finden / zu ersetzen?

KB.
quelle
1
Hinzufügen meiner Antwort als Kommentar, um sie besser sichtbar zu machen: Um es klar zu machen, entfernt TRIM standardmäßig nur Leerzeichen (nicht alle Leerzeichen). Hier ist das Dokument: dev.mysql.com/doc/refman/5.0/en/…
Mulya

Antworten:

270

Du suchst TRIM .

UPDATE FOO set FIELD2 = TRIM(FIELD2);
cwallenpoole
quelle
19
Hinweis: Dadurch werden nur reguläre Leerzeichen und keine anderen Leerzeichen (Tabulator, Zeilenumbruch usw.) entfernt
TM.
30
Ja, Sie haben Recht, @TM, also ist es besser zu verwenden: UPDATE FOO set FIELD2 = TRIM (Ersetzen (Ersetzen (Ersetzen (FIELD2, '\ t', ''), '\ n', ''), '\ r' , '')); usw.
Chris Sim
9
Obwohl die Lösung von @ ChrisSim natürlich auch innerhalb des Inhalts Zeilenumbrüche und Tabulatoren ersetzt - was wahrscheinlich nicht das ist, was die meisten Leute von einer TRIM-Funktion erwarten!
JoLoCo
41

Eine allgemeine Antwort, die ich aus Ihren Antworten und anderen Links zusammengestellt habe und die für mich funktioniert hat und die ich in einem Kommentar geschrieben habe, lautet:

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

etc.

Da trim () nicht alle Leerzeichen entfernt, ist es besser, alle gewünschten Leerzeichen zu ersetzen und sie dann zu kürzen.

Hoffe ich konnte dir helfen meine Antwort zu teilen :)

Chris Sim
quelle
7
Dadurch werden alle Tabulatoren / Zeilenumbrüche entfernt. TRIM sollte nur Leerzeichen an beiden Enden der Zeichenfolge entfernen.
DisgruntledGoat
1
Dies ist eine gute Idee, die neuen Zeilenzeichen zu denken und zu entfernen. Danke. Funktioniert wie ein Zauber. Ich habe sie positiv bewertet. Weil Chris Sim
Sankar Ganesh
25

Bitte verstehen Sie den Anwendungsfall, bevor Sie diese Lösung verwenden:

Das Trimmen funktioniert bei der Auswahlabfrage nicht

Das funktioniert

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

Während dies nicht tut

select trim(name) from test;
amitchhajer
quelle
9
TRIM()funktioniert gut für mich in einer SELECTAussage, ich bin wirklich neugierig, warum diese Antwort so viele positive Stimmen hat. Verwenden Sie MySQL? Welche Version?
Billynoah
1
Trimmen Entfernen Sie nur führende und nachfolgende
amitchhajer
11
Ja, diese Antwort ist falsch. Wie kam es zu mehr als 50 Upvotes?
Loko
5
Das ist nicht nur falsch, es ist gefährlich. Es kann die Daten von jemandem ernsthaft beschädigen.
einige-nicht-beschreibende-Benutzer
1
Ich habe abgelehnt. Testfall: Gibt SELECT CONCAT('"', TRIM(" hello world "), '"') AS `trimmed value` FROM DUALdie gewünschte Ausgabe an "hello world". Während die Ersetzungsvariante das Leerzeichen als Worttrennzeichen gefährlich entfernt: SELECT CONCAT('"', REPLACE(" hello world ", ' ', '')) AS `replaced value` FROM DUAL gibt die unerwünschte Ausgabe"helloworld"
Piemol
11

Es scheint, dass keine der aktuellen Antworten tatsächlich 100% des Leerzeichens vom Anfang und Ende einer Zeichenfolge entfernt.

Wie in anderen Beiträgen erwähnt, entfernt die Standardeinstellung TRIMnur Leerzeichen - keine Tabulatoren, Formfeeds usw. Eine Kombination von TRIMs, die andere Leerzeichen angeben, kann eine begrenzte Verbesserung bewirken, z TRIM(BOTH '\r' FROM TRIM(BOTH '\n' FROM TRIM(BOTH '\f' FROM TRIM(BOTH '\t' FROM TRIM(txt))))). Das Problem bei diesem Ansatz ist jedoch, dass nur ein einziges Zeichen für ein bestimmtes Zeichen angegeben werden kann TRIMund diese Zeichen nur am Anfang und am Ende entfernt werden. Wenn die zu schneidende Zeichenfolge so etwas wie \t \t \t \t(dh alternative Leerzeichen und Tabulatorzeichen) ist, TRIMwären mehr s erforderlich - und im allgemeinen Fall könnte dies unbegrenzt weitergehen.

Für eine einfache Lösung sollte es möglich sein, eine einfache benutzerdefinierte Funktion (User Defined Function, UDF) zu schreiben, um die Aufgabe zu erledigen, indem die Zeichen am Anfang und Ende einer Zeichenfolge durchlaufen werden. Aber ich werde das nicht tun ... da ich bereits einen etwas schwereren Ersatz für reguläre Ausdrücke geschrieben habe, der auch die Arbeit erledigen kann - und aus anderen Gründen nützlich sein kann, wie in diesem Blog-Beitrag beschrieben .

Demo

Online-Demo erneut testen . Insbesondere zeigt die letzte Zeile die anderen fehlgeschlagenen Methoden, aber die erfolgreiche Methode für reguläre Ausdrücke.

Funktion :

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

Verwendung:

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

Diese Anweisung entfernt und aktualisiert den Feldinhalt Ihrer Datenbank

So entfernen Sie Leerzeichen auf der linken Seite des Feldwerts

UPDATE-Tabelle SET field1 = LTRIM (field1);

Ex. UPDATE-Mitglied SET firstName = LTRIM (firstName);

So entfernen Sie Leerzeichen auf der rechten Seite des Feldwerts

UPDATE-Tabelle SETfield1 = RTRIM (Feld1);

Ex. UPDATE-Mitglied SET firstName = RTRIM (firstName);

luxknight_007
quelle
2

Ich musste die Werte in einer Primärschlüsselspalte mit Vor- und Nachnamen kürzen, daher wollte ich nicht den gesamten Leerraum kürzen, da dadurch der Abstand zwischen Vor- und Nachname entfernt würde, den ich beibehalten musste. Was für mich funktioniert hat war ...

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

oder

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

oder

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

Beachten Sie, dass die erste Instanz von FIELD in einfachen Anführungszeichen steht, die zweite jedoch überhaupt nicht in Anführungszeichen. Ich musste es so machen oder es gab mir einen Syntaxfehler, der besagte, dass es sich um einen doppelten Primärschlüssel handelte, wenn ich beide in Anführungszeichen hatte.

MistyDawn
quelle
1

Wenn Sie in ausgewählten Abfragen Trimmen verwenden müssen, können Sie auch reguläre Ausdrücke verwenden

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

Zeilen mit einem Feld wie 'Abfragezeichenfolge' zurückgeben

TheSameSon
quelle
0

Sie können ltrim oder rtrim verwenden, um Leerzeichen für rechts oder links oder eine Zeichenfolge zu bereinigen.

Tomer
quelle
0

Sie können das folgende SQL verwenden: UPDATE TABLESET Column= replace (Column, '', '')

Optimus Prime
quelle
-5

Ich weiß, dass es bereits akzeptiert wurde, aber für diejenigen wie mich, die nach "ALLE Leerzeichen entfernen" suchen (nicht nur am Anfang und Ende der Zeichenfolge):

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

EDIT 20.06.2019: Ja, das ist nicht gut. Die Funktion gibt den Teil der Zeichenfolge zurück, seit "als der Zeichenraum zum ersten Mal aufgetreten ist". Wenn Sie dies sagen, entfernen Sie die führenden und nachfolgenden Leerzeichen und geben das erste Wort zurück:

select SUBSTRING_INDEX(TRIM(' 1234 243'), ' ', 1);
François Breton
quelle
5
Dies hat keine Relevanz für das OP.
Mickmackusa
4
Whoah, du entfernst nicht alle Leerzeichen - du entfernst alles ab dem ersten Leerzeichen .
Timo