Як видалити простір провідних та кінцевих пробілів у полі MySQL?


134

У мене є таблиця з двома полями (країни та коди ISO):

Table1

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

У деяких рядках друге поле має пробіл на початку та / або в кінці, що впливає на запити.

Table1

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

Чи є спосіб (в SQL) пройти через таблицю і знайти / замінити пробіл у field2?


1
Додаючи мою відповідь як коментар, щоб зробити її більш помітною: просто щоб було зрозуміло, TRIM за замовчуванням видаляє лише пробіли (не всі пробіли). Ось документ: dev.mysql.com/doc/refman/5.0/en/…
mulya

Відповіді:


270

Ви шукаєте TRIM .

UPDATE FOO set FIELD2 = TRIM(FIELD2);

19
Примітка: це видаляє лише звичайні пробіли, а не інші символи пробілу (вкладка, новий рядок тощо)
TM.

30
так, ти правий @TM, тож краще використовувати: ОНОВЛЕННЯ FOO set FIELD2 = TRIM (Замінити (Замінити (Замінити (FIELD2, '\ t', '')), '\ n', ''), '\ r' , '')); і т. д.
Кріс Сім

9
Хоча рішення @ ChrisSim замінить нові рядки та вкладки ВІД вмісту, звичайно, що, мабуть, не те, що більшість людей хоче від функції TRIM!
JoLoCo

41

Загальна відповідь, яку я склав з ваших відповідей та з інших посилань, і це працювало на мене, і я написав це в коментарі:

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

тощо.

Оскільки обробка () не видаляє всі пробіли білого кольору, тож краще замінити всі білі простори на потрібне, а не обрізати.

Сподіваюся, я міг допомогти вам поділитися своєю відповіддю :)


7
Це видаляє всі вкладки / нові рядки. TRIM повинен видаляти пробіли лише на будь-якому кінці рядка.
НезадоволенеЗакриття

1
це гарна ідея мислення та видалення нових символів рядка, спасибі. Працює як шарм, я відмовився від цього, bcoz для цього мислення @Chris Sim
Ganesh

25

Будь ласка, зрозумійте випадок використання перед використанням цього рішення:

обробка не працює під час вибору запиту

Це працює

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

Поки цього немає

select trim(name) from test;

9
TRIM()Для мене добре працює в SELECTзаяві, мені дуже цікаво, чому ця відповідь отримала так багато відгуків. Ви використовуєте mysql? Яка версія?
billynoah

1
обрізати лише видалити провідні та кінцеві пробіли dev.mysql.com/doc/refman/5.7/uk/string-functions.html
amitchhajer

11
Так, ця відповідь неправильна. Як це отримало 50+ оновлень?
Локо

5
Це не тільки неправильно, це небезпечно. Це може серйозно зіпсувати чиїсь дані.
не описує описів,

1
Я відмовився. Тестова скринька: SELECT CONCAT('"', TRIM(" hello world "), '"') AS `trimmed value` FROM DUALдає потрібний вихід "hello world". Хоча варіант заміни небезпечно видаляє простір як роздільник слів: SELECT CONCAT('"', REPLACE(" hello world ", ' ', '')) AS `replaced value` FROM DUAL дає небажаний вихід"helloworld"
Piemol


11

Здається, жоден з поточних відповідей насправді не видалить 100% пробілів з початку та в кінці рядка.

Як було зазначено в інших публікаціях, за замовчуванням TRIMвидаляються лише пробіли - не вкладки, формати тощо. Комбінація TRIMs, що визначає інші символи пробілу, може забезпечити обмежене поліпшення, наприклад TRIM(BOTH '\r' FROM TRIM(BOTH '\n' FROM TRIM(BOTH '\f' FROM TRIM(BOTH '\t' FROM TRIM(txt))))). Але проблема такого підходу полягає в тому, що для конкретного конкретного конкретного персонажа може бути вказаний лише один символ, TRIMі ці символи видаляються лише з початку та в кінці. Тож якщо обрізана рядок - це щось на зразок \t \t \t \t(тобто альтернативні пробіли та символи вкладки), більшеTRIM знадобиться s - і в загальному випадку це може тривати нескінченно.

Для легкого рішення слід створити просту функцію, визначену користувачем (UDF), щоб виконати цю роботу, перебираючи символи на початку та в кінці рядка. Але я не збираюся цього робити ... так як я вже написав досить важкий замінник регулярних виразів, який також може зробити цю роботу - і може стати корисним з інших причин, як описано в цій публікації в блозі .

Демо

Інтернет-демонстрація Rextester . Зокрема, в останньому рядку показано, що інші методи не вдається, але метод регулярного вираження є успішним.

Функція :

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

Використання:

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

4

Ця заява видалить та оновить вміст поля вашої бази даних

Щоб видалити пробіли в лівій частині значення поля

ОНОВЛЕННЯ таблиці SET SET1 = LTRIM (поле1);

колишній ОНОВЛЕННЯ учасника SET firstName = LTRIM (firstName);

Щоб видалити пробіли в правій частині значення поля

ОНОВЛЕННЯ таблиці SETfield1 = RTRIM (поле1);

колишній ОНОВЛЕННЯ учасника SET firstName = RTRIM (firstName);


2

Мені потрібно було обрізати значення в стовпці первинного ключа, який мав ім’я та прізвище, тому я не хотів обрізати весь пробіл, оскільки це видалить простір між ім'ям та прізвищем, яке мені потрібно було зберегти. Що для мене працювало ...

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

або

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

або

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

Зауважте, що перший екземпляр FIELD знаходиться в одинарних лапках, а другий взагалі не в лапках. Я повинен був зробити це таким чином, або це призвело до помилки синтаксису, кажучи, що це дублікат первинного ключа, коли я мав обидва в лапках.


1

Якщо вам потрібно використовувати обрізку для вибору запиту, ви також можете використовувати регулярні вирази

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

повернути рядки з полем типу "рядок запитів"


0

ви можете використовувати ltrim або rtrim для очищення білих просторів праворуч або ліворуч або рядок.



-5

Я знаю, що це вже прийнято, але для таких, як я, які шукають "видалити ВСІ пробіли" (не лише на початку та в кінці рядка):

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

EDIT 2019/6/20: Так, це не добре. Функція повертає частину рядка з "коли вперше відбувся пробіл символів". Отже, я думаю, що сказавши це, вилучіть провідні та проміжні пробіли та повернете перше слово:

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

5
Це не має стосунку до ОП.
mickmackusa

4
Ну, ти не видаляєш усіх пробілів - ти видаляєш все з першого простору вперед .
Тимо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.