MySQL - รหัสไปรษณีย์แผ่นหน้าด้วย“ 0” ได้อย่างไร?


93

ในฐานข้อมูล MySQL InnoDB ของฉันฉันมีข้อมูลรหัสไปรษณีย์สกปรกที่ฉันต้องการล้างข้อมูล

ข้อมูลรหัสไปรษณีย์ที่สะอาดคือเมื่อฉันมีตัวเลข 5 หลักสำหรับรหัสไปรษณีย์ (เช่น "90210")

แต่ด้วยเหตุผลบางอย่างฉันสังเกตเห็นในฐานข้อมูลของฉันว่าสำหรับรหัสไปรษณีย์ที่ขึ้นต้นด้วย "0" นั้น 0 จะถูกทิ้ง

ดังนั้น " Holtsville, New York " ที่มีรหัสไปรษณีย์ " 00544" จึงถูกเก็บไว้ในฐานข้อมูลของฉันเป็น " 544"

และ

" Dedham, MA " พร้อมรหัสไปรษณีย์ " 02026" ถูกเก็บไว้ในฐานข้อมูลของฉันเป็น " 2026"

ฉันสามารถเรียกใช้ SQL ใดที่แป้นด้านหน้า "0" ไปยังรหัสไปรษณีย์ที่มีความยาวไม่เกิน 5 หลัก หมายความว่าถ้ารหัสไปรษณีย์มีความยาว 3 หลักให้กดแป้นด้านหน้า "00" หากรหัสไปรษณีย์มีความยาว 4 หลักให้กดแป้นด้านหน้าเพียง "0"

อัพเดท :

ฉันเพิ่งเปลี่ยนรหัสไปรษณีย์เป็นประเภทข้อมูล VARCHAR (5)


3
ดูเหมือนว่าคอลัมน์ตารางสำหรับรหัสไปรษณีย์เป็นประเภท Number และนั่นเป็นสาเหตุของปัญหา ในกรณีนี้คุณจะต้องเปลี่ยนประเภทข้อมูลเพื่อเก็บข้อมูลอักขระ
กังกัน

1
@ คุณกังกานต์คุณถูกต้อง ประเภทข้อมูลของฉันคือตัวเลข ฉันเพิ่งแปลงรหัสไปรษณีย์เป็น varchar (5) ตอนนี้จะไปที่หน้า <5 หลัก zipcodes ด้วย "0" ได้อย่างไร
TeddyR

1
ควรใช้ CHAR แทน VARCHAR มันจะเร่งการสืบค้นขึ้นมากเมื่อตารางมีขนาดใหญ่ (เฉพาะในกรณีที่คอลัมน์อื่น ๆ ทั้งหมดของคุณมีขนาดคงที่)
quantumSoup

2
นอกจากนี้โปรดพิจารณารหัสไปรษณีย์จากประเทศอื่น ๆ ไม่ใช่ 5 ตัวอักษรเสมอไป
Bill Karwin

คำตอบ:


219

จัดเก็บรหัสไปรษณีย์ของคุณเป็น CHAR (5) แทนประเภทตัวเลขหรือให้แผ่นแอปพลิเคชันของคุณมีศูนย์เมื่อคุณโหลดจากฐานข้อมูล วิธีดำเนินการกับ PHP โดยใช้sprintf():

echo sprintf("%05d", 205); // prints 00205
echo sprintf("%05d", 1492); // prints 01492

หรือคุณอาจมีแผ่น MySQL ให้คุณด้วยLPAD():

SELECT LPAD(zip, 5, '0') as zipcode FROM table;

นี่คือวิธีการอัปเดตและวางแถวทั้งหมด:

ALTER TABLE `table` CHANGE `zip` `zip` CHAR(5); #changes type
UPDATE table SET `zip`=LPAD(`zip`, 5, '0'); #pads everything

ฉันต้องการล้างข้อมูลของฉันในฐานข้อมูลจริงๆ คุณรู้หรือไม่ว่าเทียบเท่ากับ SQL?
TeddyR

1
ฉันรันโค้ดต่อไปนี้ที่ทำให้มันใช้งานได้ "UPDATE tablename SET zip = LPAD (zip, 5, '0');"
TeddyR

ฉันขอยืนยันว่าคำตอบที่ 'ยอมรับ' นี้ไม่ดีเท่าZEROFILLคำตอบ
Rick James

ข้อบกพร่องในคำตอบนี้ หากค่าดีฟอลต์CHARACTER SETคือ utf8 นั่นCHAR(5)จะใช้เวลา 15 ไบต์โดยไม่จำเป็น!
Rick James

19

คุณต้องกำหนดความยาวของรหัสไปรษณีย์ (ซึ่งฉันเชื่อว่าควรมีความยาว 5 อักขระ) จากนั้นคุณต้องบอก MySQL ให้เติมตัวเลขเป็นศูนย์

สมมติว่าตารางของคุณเรียกว่าmytableและเขตในคำถามคือชนิดzipcode smallintคุณต้องออกแบบสอบถามต่อไปนี้:

ALTER TABLE mytable CHANGE `zipcode` `zipcode`
    MEDIUMINT( 5 ) UNSIGNED ZEROFILL NOT NULL;

ข้อดีของวิธีนี้คือทำให้ข้อมูลของคุณไม่เสียหายไม่จำเป็นต้องใช้ทริกเกอร์ระหว่างการแทรก / อัปเดตข้อมูลไม่จำเป็นต้องใช้ฟังก์ชันเมื่อคุณSELECTป้อนข้อมูลและคุณสามารถลบเลขศูนย์พิเศษหรือเพิ่มความยาวของฟิลด์ได้เสมอ คุณเปลี่ยนใจ


3
Zerofill ที่ไม่ได้ลงชื่อเป็นวิธีที่จะไปแม้ว่า smallint จะออกมาสูงสุดที่ 65535 ฉันขอแนะนำ mediumint กาลีมีซิป 9xxxx
brandon-estrella-dev

4
หากคุณต้องการสนับสนุนรหัสไปรษณีย์สำหรับประเทศอื่น ๆ คุณไม่ต้องการจำนวนเต็ม บางประเทศใช้ตัวอักษรในรหัสไปรษณีย์ของตน
Wodin

12

โอเคคุณได้เปลี่ยนคอลัมน์จาก Number เป็น VARCHAR (5) แล้ว ตอนนี้คุณต้องอัปเดตช่องรหัสไปรษณีย์เป็นเบาะด้านซ้าย SQL ที่จะทำคือ:

UPDATE MyTable
SET ZipCode = LPAD( ZipCode, 5, '0' );

การดำเนินการนี้จะเพิ่มค่าทั้งหมดในคอลัมน์ ZipCode เป็น 5 อักขระโดยเพิ่ม '0 ทางด้านซ้าย

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

  • จัดการกับตรรกะทางธุรกิจของแอปพลิเคชัน ข้อดี: โซลูชันที่ไม่ขึ้นกับฐานข้อมูลไม่เกี่ยวข้องกับการเรียนรู้เพิ่มเติมเกี่ยวกับฐานข้อมูล ข้อเสีย: ต้องจัดการทุกที่ที่เขียนไปยังฐานข้อมูลในทุกแอปพลิเคชัน

  • จัดการกับขั้นตอนการจัดเก็บ ข้อดี: ขั้นตอนที่จัดเก็บไว้บังคับใช้กฎทางธุรกิจสำหรับลูกค้าทั้งหมด ข้อเสีย: ขั้นตอนที่จัดเก็บมีความซับซ้อนกว่าคำสั่ง INSERT / UPDATE แบบธรรมดาและไม่สามารถพกพาได้ในฐานข้อมูล INSERT / UPDATE เปล่ายังคงสามารถแทรกข้อมูลที่ไม่มีเบาะเป็นศูนย์ได้

  • จัดการกับทริกเกอร์ ข้อดี: จะใช้ได้กับ Stored Procedures และคำสั่ง INSERT / UPDATE แบบเปลือย ข้อเสีย: โซลูชันแบบพกพาน้อยที่สุด วิธีแก้ปัญหาที่ช้าที่สุด ทริกเกอร์อาจทำได้ยาก

ในกรณีนี้ฉันจะจัดการในระดับแอปพลิเคชัน (ถ้ามี) ไม่ใช่ระดับฐานข้อมูล ท้ายที่สุดไม่ใช่ทุกประเทศที่ใช้รหัสไปรษณีย์ 5 หลัก (ไม่ใช่สหรัฐอเมริกา - รหัสไปรษณีย์ของเราคือ Zip + 4 + 2: nnnnn-nnnn-nn) และบางประเทศอนุญาตให้ใช้ตัวอักษรและตัวเลข อย่าพยายามบังคับรูปแบบข้อมูลและยอมรับข้อผิดพลาดของข้อมูลเป็นครั้งคราวแทนที่จะป้องกันไม่ให้ใครป้อนค่าที่ถูกต้องแม้ว่ารูปแบบจะไม่เป็นไปตามที่คุณคาดหวังก็ตาม


4

ฉันรู้ดีหลังจาก OP วิธีหนึ่งที่คุณสามารถทำได้เพื่อให้ตารางจัดเก็บข้อมูลรหัสไปรษณีย์เป็น INT ที่ไม่ได้ลงชื่อ แต่แสดงด้วยศูนย์มีดังนี้

select LPAD(cast(zipcode_int as char), 5, '0') as zipcode from table;

แม้ว่าสิ่งนี้จะเก็บรักษาข้อมูลต้นฉบับเป็น INT และสามารถประหยัดพื้นที่ในการจัดเก็บได้คุณจะต้องให้เซิร์ฟเวอร์ทำการแปลง INT เป็น CHAR ให้กับคุณ สิ่งนี้สามารถโยนลงในมุมมองและผู้ที่ต้องการข้อมูลนี้สามารถถูกนำไปที่นั่นเทียบกับตารางได้


3

คุณควรสร้างฟิลด์รหัสไปรษณีย์ของคุณเป็นฟิลด์จำนวนเต็มที่ไม่มีเครื่องหมาย zerofilled

CREATE TABLE xxx ( zipcode INT(5) ZEROFILL UNSIGNED, ... )

ทาง mysql จะดูแลช่องว่างภายในให้คุณ


3
CHAR(5)

หรือ

MEDIUMINT (5) UNSIGNED ZEROFILL

ครั้งแรกใช้เวลา 5 ไบต์ต่อรหัสไปรษณีย์

อย่างที่สองใช้เวลาเพียง 3 ไบต์ต่อรหัสไปรษณีย์ ตัวเลือก ZEROFILL จำเป็นสำหรับรหัสไปรษณีย์ที่มีเลขศูนย์นำหน้า



0

LPAD ทำงานร่วมกับ VARCHAR2 เนื่องจากไม่ได้ใส่ช่องว่างสำหรับไบต์ที่เหลือ LPAD เปลี่ยนไบต์ที่เหลือ / null เป็นศูนย์บนประเภทข้อมูล LHS SO ควรเป็น VARCHAR2

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