MySQL - làm thế nào để mã zip vùng đệm phía trước với “0”?


89

Trong cơ sở dữ liệu MySQL InnoDB của tôi, tôi có dữ liệu mã zip bẩn mà tôi muốn xóa.

Dữ liệu mã zip sạch là khi tôi có tất cả 5 chữ số cho mã zip (ví dụ: "90210").

Nhưng vì lý do nào đó, tôi nhận thấy trong cơ sở dữ liệu của mình rằng đối với các mã zip bắt đầu bằng "0", số 0 đã bị loại bỏ.

Vì vậy, " Holtsville, New York " với mã zip " 00544" được lưu trữ trong cơ sở dữ liệu của tôi là " 544"

" Dedham, MA " với mã vùng " 02026" được lưu trữ trong cơ sở dữ liệu của tôi dưới dạng " 2026".

Tôi có thể chạy SQL nào đến vùng đệm trước "0" tới bất kỳ mã zip nào không có độ dài 5 chữ số? Có nghĩa là, nếu mã zip có độ dài 3 chữ số, thì đệm trước "00". Nếu mã zip có độ dài 4 chữ số, phần đệm phía trước chỉ là "0".

CẬP NHẬT :

Tôi vừa thay đổi mã zip thành kiểu dữ liệu VARCHAR (5)


3
Có vẻ như cột bảng cho mã zip thuộc loại Số và điều đó đang gây ra sự cố. Trong trường hợp đó, bạn sẽ phải thay đổi kiểu dữ liệu để giữ dữ liệu ký tự.
Kangkan

1
@Kangkan, bạn nói đúng. Kiểu dữ liệu của tôi là một số. Tôi vừa chuyển đổi mã zip thành varchar (5). Bây giờ, làm thế nào để truy cập trang đầu <mã zip 5 chữ số với "0"?
TeddyR

1
Tốt hơn nên sử dụng CHAR thay vì VARCHAR. Nó sẽ tăng tốc độ truy vấn bởi rất nhiều khi bảng được lớn (kích thước chỉ khi tất cả các cột khác của bạn đã cố định mặc dù)
quantumSoup

2
Cũng nên xem xét mã bưu chính từ các quốc gia khác không phải lúc nào cũng có 5 ký tự.
Bill Karwin

Câu trả lời:


214

Lưu trữ mã zip của bạn dưới dạng CHAR (5) thay vì loại số hoặc đặt ứng dụng của bạn bằng các số 0 khi bạn tải nó từ DB. Một cách để làm điều đó với PHP bằng cách sử dụng sprintf():

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

Hoặc bạn có thể có MySQL đệm nó cho bạn với LPAD():

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

Đây là một cách để cập nhật và đệm tất cả các hàng:

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

Tôi thực sự muốn dọn dẹp dữ liệu của mình trong chính cơ sở dữ liệu. Bạn có biết cách tương đương để làm điều này với SQL không?
TeddyR

1
Tôi đã chạy mã sau làm cho nó hoạt động "CẬP NHẬT tên bảng SET zip = LPAD (zip, 5, '0');"
TeddyR

Tôi cho rằng câu trả lời 'được chấp nhận' này không tốt bằng ZEROFILLcâu trả lời.
Rick James

Một lỗ hổng trong câu trả lời này. Nếu mặc định CHARACTER SETlà utf8, nó CHAR(5)sẽ chiếm 15 byte một cách không cần thiết!
Rick James

19

Bạn cần quyết định độ dài của mã zip (mà tôi tin rằng phải dài 5 ký tự). Sau đó, bạn cần yêu cầu MySQL điền các số bằng không.

Giả sử bảng của bạn được gọi mytablevà trường được đề cập là zipcode, nhập smallint. Bạn cần đưa ra truy vấn sau:

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

Ưu điểm của phương pháp này là giữ nguyên dữ liệu của bạn, không cần sử dụng trình kích hoạt trong quá trình chèn / cập nhật dữ liệu, không cần sử dụng các hàm khi bạn SELECTdữ liệu và bạn luôn có thể loại bỏ các số không thừa hoặc tăng độ dài trường. bạn thay đổi suy nghĩ của bạn.


3
Không ký tên Zerofill là một cách để đi, mặc dù smallint đạt tối đa ở mức 65535. Tôi đề xuất phương tiện. Cali có zips là 9xxxx.
brandon-estrella-dev

4
Nếu bạn muốn hỗ trợ mã bưu chính cho các quốc gia khác, bạn không muốn một số nguyên. Một số quốc gia sử dụng chữ cái trong mã bưu điện của họ.
Wodin

11

Ok, vậy là bạn đã chuyển cột từ Number sang VARCHAR (5). Bây giờ bạn cần cập nhật trường mã zip được đệm bên trái. SQL để làm điều đó sẽ là:

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

Điều này sẽ đệm tất cả các giá trị trong cột ZipCode thành 5 ký tự, thêm '0 ở bên trái.

Tất nhiên, bây giờ bạn đã sửa tất cả dữ liệu cũ của mình, bạn cần đảm bảo rằng mọi dữ liệu mới của bạn cũng không có đệm. Có một số trường phái suy nghĩ về cách chính xác để làm điều đó:

  • Xử lý nó trong logic nghiệp vụ của ứng dụng. Ưu điểm: giải pháp độc lập với cơ sở dữ liệu, không liên quan đến việc tìm hiểu thêm về cơ sở dữ liệu. Nhược điểm: cần được xử lý ở mọi nơi ghi vào cơ sở dữ liệu, trong tất cả các ứng dụng.

  • Xử lý nó bằng một thủ tục được lưu trữ. Ưu điểm: Các thủ tục được lưu trữ thực thi các quy tắc kinh doanh cho tất cả các khách hàng. Nhược điểm: Các thủ tục được lưu trữ phức tạp hơn so với các câu lệnh INSERT / UPDATE đơn giản và không dễ di chuyển trên các cơ sở dữ liệu. INSERT / UPDATE trống vẫn có thể chèn dữ liệu không đệm.

  • Xử lý nó bằng cò súng. Ưu điểm: Sẽ hoạt động với các thủ tục được lưu trữ và câu lệnh INSERT / UPDATE trần. Nhược điểm: Ít giải pháp di động. Giải pháp chậm nhất. Có thể khó kích hoạt đúng.

Trong trường hợp này, tôi sẽ xử lý nó ở cấp ứng dụng (nếu có), chứ không phải cấp cơ sở dữ liệu. Rốt cuộc, không phải tất cả các quốc gia đều sử dụng Zipcode gồm 5 chữ số (thậm chí không phải Hoa Kỳ - mã zip của chúng tôi thực sự là Zip + 4 + 2: nnnnn-nnnn-nn) và một số cho phép cả chữ cái cũng như chữ số. Tốt hơn là KHÔNG nên thử và ép buộc một định dạng dữ liệu và chấp nhận lỗi dữ liệu không thường xuyên, hơn là ngăn ai đó nhập giá trị chính xác, mặc dù định dạng đó không hoàn toàn như bạn mong đợi.


4

Tôi biết điều này là tốt sau OP. Một cách bạn có thể thực hiện để giữ cho bảng lưu trữ dữ liệu mã zip dưới dạng INT không dấu nhưng được hiển thị bằng số không là như sau.

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

Trong khi điều này bảo toàn dữ liệu gốc dưới dạng INT và có thể tiết kiệm một số không gian lưu trữ, bạn sẽ yêu cầu máy chủ thực hiện chuyển đổi INT sang CHAR cho bạn. Điều này có thể được đưa vào một khung nhìn và người cần dữ liệu này có thể được dẫn đến đó so với chính bảng đó.


3

Sẽ vẫn có ý nghĩa nếu tạo trường mã zip của bạn dưới dạng một trường số nguyên không dấu không điền.

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

Bằng cách đó, mysql sẽ chăm sóc phần đệm cho bạn.


3
CHAR(5)

hoặc là

MEDIUMINT (5) UNSIGNED ZEROFILL

Đầu tiên có 5 byte cho mỗi mã zip.

Thứ hai chỉ mất 3 byte cho mỗi mã zip. Tùy chọn ZEROFILL cần thiết cho các mã zip có số 0 ở đầu.



0

LPAD hoạt động với VARCHAR2 vì nó không đặt khoảng trắng cho các byte còn lại. LPAD thay đổi byte còn lại / rỗng thành số không trên kiểu dữ liệu LHS SO phải là VARCHAR2

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.