MySQL - bagaimana kode pos front pad dengan "0"?

93

Dalam database MySQL InnoDB saya, saya memiliki data kode pos kotor yang ingin saya bersihkan.

Data kode pos bersih adalah ketika saya memiliki semua 5 digit untuk kode pos (mis. "90210").

Tetapi untuk beberapa alasan, saya perhatikan dalam database saya bahwa untuk kode pos yang dimulai dengan "0", 0 telah dihapus.

Jadi " Holtsville, New York " dengan kode pos " 00544" disimpan dalam database saya sebagai " 544"

dan

" Dedham, MA " dengan kode pos " 02026" disimpan dalam database saya sebagai " 2026".

SQL apa yang dapat saya jalankan ke panel depan "0" ke kode pos yang panjangnya tidak 5 digit? Artinya, jika kode pos panjangnya 3 digit, pad depan "00". Jika kode pos terdiri dari 4 digit, pad depan hanya "0".

UPDATE :

Saya baru saja mengubah kode pos menjadi tipe data VARCHAR (5)

TeddyR
sumber
3
Tampaknya kolom tabel untuk kode pos berjenis Number dan itulah yang menyebabkan masalah. Dalam hal ini, Anda harus mengubah tipe data untuk menyimpan data karakter.
Kangkan
1
@Kangkan, kamu benar. Tipe data saya adalah angka. Saya baru saja mengonversi kode pos menjadi varchar (5). Sekarang, bagaimana cara membuka kode pos <5 digit dengan "0"?
TeddyR
1
Lebih baik menggunakan CHAR daripada VARCHAR. Ini akan mempercepat kueri dengan banyak ketika tabel menjadi besar (hanya jika semua kolom Anda yang lain memiliki ukuran tetap)
quantumSoup
2
Pertimbangkan juga kode pos dari negara lain tidak selalu 5 karakter.
Bill Karwin

Jawaban:

219

Simpan kode pos Anda sebagai CHAR (5) alih-alih tipe numerik, atau minta aplikasi Anda membungkusnya dengan nol saat Anda memuatnya dari DB. Cara melakukannya dengan PHP menggunakan sprintf():

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

Atau Anda bisa memiliki MySQL pad untuk Anda dengan LPAD():

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

Berikut cara untuk memperbarui dan mengisi semua baris:

ALTER TABLE `table` CHANGE `zip` `zip` CHAR(5); #changes type
UPDATE table SET `zip`=LPAD(`zip`, 5, '0'); #pads everything
quantumSoup
sumber
Saya ingin benar-benar membersihkan data saya di database itu sendiri. Apakah Anda tahu cara melakukan ini dengan SQL?
TeddyR
1
Saya menjalankan kode berikut yang membuatnya bekerja "UPDATE tablename SET zip = LPAD (zip, 5, '0');"
TeddyR
Saya berpendapat bahwa jawaban yang 'diterima' ini tidak sebaik ZEROFILLjawaban.
Rick James
Cacat dalam jawaban ini. Jika defaultnya CHARACTER SETadalah utf8, itu CHAR(5)akan memakan waktu 15 byte!
Rick James
19

Anda perlu menentukan panjang kode pos (yang menurut saya harus terdiri dari 5 karakter). Maka Anda perlu memberi tahu MySQL untuk mengisi nol angka.

Misalkan tabel Anda dipanggil mytabledan bidang yang dimaksud adalah zipcode, ketik smallint. Anda perlu mengeluarkan pertanyaan berikut:

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

Keuntungan dari metode ini adalah ia membiarkan data Anda tetap utuh, tidak perlu menggunakan pemicu selama penyisipan / pembaruan data, tidak perlu menggunakan fungsi saat Anda SELECTmemasukkan data dan Anda selalu dapat menghapus nol ekstra atau menambah panjang bidang. Anda berubah pikiran.

Anax
sumber
3
Unsigned Zerofill adalah pilihan yang tepat, meskipun smallint maxes di 65535. Saya sarankan mediumint. Cali memiliki ritsleting 9xxxx.
brandon-estrella-dev
4
Jika Anda ingin mendukung kode pos untuk negara lain, Anda tidak ingin bilangan bulat. Beberapa negara menggunakan huruf dalam kode pos mereka.
Wodin
12

Oke, jadi Anda telah mengalihkan kolom dari Angka ke VARCHAR (5). Sekarang Anda perlu memperbarui bidang kode pos menjadi bantalan kiri. SQL untuk melakukannya adalah:

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

Ini akan menambah semua nilai di kolom Kode Pos menjadi 5 karakter, menambahkan '0 di sebelah kiri.

Tentu saja, sekarang setelah semua data lama Anda diperbaiki, Anda perlu memastikan bahwa data baru Anda juga tidak memiliki bantalan. Ada beberapa aliran pemikiran tentang cara yang benar untuk melakukan itu:

  • Tangani dalam logika bisnis aplikasi. Keuntungan: solusi database-independent, tidak melibatkan mempelajari lebih lanjut tentang database. Kekurangan: perlu ditangani di mana saja yang menulis ke database, di semua aplikasi.

  • Tangani dengan prosedur tersimpan. Keuntungan: Prosedur tersimpan memberlakukan aturan bisnis untuk semua klien. Kekurangan: Prosedur tersimpan lebih rumit daripada pernyataan INSERT / UPDATE sederhana, dan tidak portabel di seluruh database. INSERT / UPDATE kosong masih dapat memasukkan data non-zero-padded.

  • Tangani dengan pemicu. Keuntungan: Akan berfungsi untuk Prosedur Tersimpan dan pernyataan INSERT / UPDATE kosong. Kekurangan: Solusi portabel paling sedikit. Solusi paling lambat. Pemicu mungkin sulit dilakukan dengan benar.

Dalam hal ini, saya akan menanganinya di level aplikasi (jika ada), dan bukan level database. Lagipula, tidak semua negara menggunakan Kode Pos 5 digit (bahkan tidak di AS - kode pos kami sebenarnya adalah Zip + 4 + 2: nnnnn-nnnn-nn) dan beberapa mengizinkan huruf serta angka. Lebih baik TIDAK mencoba dan memaksa format data dan menerima kesalahan data sesekali, daripada mencegah seseorang memasukkan nilai yang benar, meskipun formatnya tidak seperti yang Anda harapkan.

Craig Trader
sumber
4

Saya tahu ini baik setelah OP. Salah satu cara Anda dapat melakukannya dengan membuat tabel menyimpan data kode pos sebagai INT yang tidak ditandatangani tetapi ditampilkan dengan nol adalah sebagai berikut.

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

Meskipun ini mempertahankan data asli sebagai INT dan dapat menghemat ruang di penyimpanan, Anda akan meminta server melakukan konversi INT ke CHAR untuk Anda. Ini dapat dilemparkan ke tampilan dan orang yang membutuhkan data ini dapat diarahkan ke sana vs tabel itu sendiri.

lemming622
sumber
3

Akan tetap masuk akal untuk membuat bidang kode pos Anda sebagai bidang bilangan bulat tak bertanda tangan yang diisi ke nol.

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

Dengan cara itu mysql mengurus padding untuk Anda.

Peter
sumber
3
CHAR(5)

atau

MEDIUMINT (5) UNSIGNED ZEROFILL

Yang pertama membutuhkan 5 byte per kode pos.

Yang kedua hanya membutuhkan 3 byte per kode pos. Opsi ZEROFILL diperlukan untuk kode pos dengan nol di depan.

Martin Sansone - MiOEE
sumber
3

Anda harus menggunakannya UNSIGNED ZEROFILLdalam struktur tabel Anda.

Saurabh Chandra Patel
sumber
0

LPAD bekerja dengan VARCHAR2 karena tidak memberikan spasi untuk byte yang tersisa. LPAD mengubah byte sisa / null menjadi nol pada tipe data LHS SO harus VARCHAR2

Agen Mahone
sumber