จะลบช่องว่างนำหน้าและต่อท้ายในฟิลด์ MySQL ได้อย่างไร


141

ฉันมีตารางที่มีสองช่อง (ประเทศและรหัส 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) เพื่อไปยังตารางและค้นหา / แทนที่ช่องว่างในฟิลด์ 2 หรือไม่


1
การเพิ่มคำตอบของฉันเป็นความคิดเห็นเพื่อให้มองเห็นได้ชัดเจนขึ้น: เพื่อให้ชัดเจน TRIM โดยค่าเริ่มต้นจะลบช่องว่างเท่านั้น นี่คือเอกสาร: dev.mysql.com/doc/refman/5.0/th/…
mulya

คำตอบ:


283

คุณกำลังมองหาTRIM

UPDATE FOO set FIELD2 = TRIM(FIELD2);

19
หมายเหตุ: สิ่งนี้จะลบเฉพาะช่องว่างปกติและไม่ใช่อักขระเว้นวรรคอื่น ๆ (แท็บขึ้นบรรทัดใหม่ ฯลฯ )
TM

30
ใช่คุณพูดถูก @TM ดังนั้นจึงดีกว่าที่จะใช้: UPDATE FOO set FIELD2 = TRIM (แทนที่ (แทนที่ (แทนที่ (FIELD2, '\ t', ''), '\ n', ''), '\ r' , '')); ฯลฯ
Chris Sim

10
แม้ว่าโซลูชันของ @ ChrisSim จะแทนที่บรรทัดใหม่และแท็บภายในเนื้อหาด้วยแน่นอนซึ่งอาจไม่ใช่สิ่งที่คนส่วนใหญ่ต้องการจากฟังก์ชัน TRIM!
JoLoCo

41

คำตอบทั่วไปที่ฉันเขียนขึ้นจากคำตอบของคุณและจากลิงก์อื่น ๆ และได้ผลสำหรับฉันและฉันเขียนไว้ในความคิดเห็นคือ:

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

เป็นต้น

เนื่องจากการตัดแต่ง () ไม่ได้ลบช่องว่างสีขาวทั้งหมดดังนั้นจึงควรแทนที่ช่องว่างสีขาวทั้งหมดที่คุณต้องการและดีกว่าการตัดแต่ง

หวังว่าฉันจะช่วยคุณแบ่งปันคำตอบของฉัน :)


8
การดำเนินการนี้จะลบแท็บ / บรรทัดใหม่ทั้งหมด TRIM ควรลบช่องว่างที่ปลายด้านใดด้านหนึ่งของสตริงเท่านั้น
แพะไม่พอใจ

1
นี่เป็นความคิดที่ดีในการคิดและลบอักขระบรรทัดใหม่ขอบคุณทำงานเหมือนมีเสน่ห์ฉันได้โหวตแล้ว bcoz สำหรับความคิดนี้ @Chris Sim
Sankar Ganesh PMP

24

โปรดทำความเข้าใจกรณีการใช้งานก่อนใช้วิธีนี้:

การตัดแต่งไม่ทำงานขณะทำแบบสอบถามแบบเลือก

นี้ได้ผล

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

ขณะนี้ไม่ได้

select trim(name) from test;

10
TRIM()ใช้งานได้ดีสำหรับฉันในSELECTแถลงการณ์ฉันสงสัยจริงๆว่าทำไมคำตอบนี้ถึงได้รับการโหวตมากเกินไป คุณใช้ mysql หรือไม่? รุ่นอะไร?
billynoah

1
ตัดแต่งลบช่องว่างนำหน้าและต่อท้ายเท่านั้นdev.mysql.com/doc/refman/5.7/en/string-functions.html
amitchhajer

12
ใช่คำตอบนี้ผิด สิ่งนี้ได้รับ 50+ upvotes ได้อย่างไร?
Loko

5
นี่ไม่ใช่แค่ผิดเท่านั้นมันอันตราย มันสามารถเข้าใจข้อมูลของใครบางคนได้อย่างจริงจัง
บางส่วนที่ไม่สามารถอธิบายได้

2
ฉันโหวตลง TestCase: ช่วยให้การส่งออกต้องการ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เพียงเอาช่องว่าง - ไม่ได้แท็บ formfeeds ฯลฯ การรวมกันของ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ก็จะต้องมีจำนวนมากขึ้น- และในกรณีทั่วไปสิ่งนี้อาจดำเนินต่อไปเรื่อย ๆ

สำหรับโซลูชันที่มีน้ำหนักเบาควรเขียน User Defined Function (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;

น่าประทับใจทีเดียว! บน MySQL 8+ สามารถใช้งานใหม่ได้REGEXP_REPLACE()
oriadam

4

คำสั่งนี้จะลบและอัปเดตเนื้อหาฟิลด์ของฐานข้อมูลของคุณ

เพื่อลบช่องว่างทางด้านซ้ายของค่าฟิลด์

อัพเดตตาราง SET field1 = LTRIM (field1);

เช่น อัปเดตสมาชิก SET firstName = LTRIM (firstName);

เพื่อลบช่องว่างทางด้านขวาของค่าฟิลด์

ตารางอัพเดต SETfield1 = RTRIM (field1);

เช่น อัปเดตสมาชิก 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 *'

ส่งคืนแถวที่มีฟิลด์เช่น 'query-string'




-5

ฉันรู้ว่ามันได้รับการยอมรับแล้ว แต่สำหรับพวกอย่างฉันที่มองหา "ลบช่องว่างทั้งหมด" (ไม่ใช่แค่จุดเริ่มต้นและจุดสิ้นสุดของสตริง):

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

แก้ไข 2019/6/20:ใช่มันไม่ดี ฟังก์ชันจะส่งคืนส่วนของสตริงตั้งแต่ "เมื่อเกิดช่องว่างอักขระเป็นครั้งแรก" ดังนั้นฉันเดาว่าการพูดแบบนี้จะลบช่องว่างที่นำหน้าและต่อท้ายและส่งกลับคำแรก:

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

5
สิ่งนี้ไม่มีความเกี่ยวข้องกับ OP
mickmackusa

4
whoah คุณไม่ได้ลบช่องว่างทั้งหมด - คุณลบทุกอย่างจากพื้นที่แรกเป็นต้นไป
Timo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.