Apakah ada standar untuk menyimpan nomor telepon yang dinormalisasi dalam database?

95

Apa struktur data yang baik untuk menyimpan nomor telepon di bidang database? Saya mencari sesuatu yang cukup fleksibel untuk menangani nomor internasional, dan juga sesuatu yang memungkinkan berbagai bagian nomor dipertanyakan secara efisien.

Sunting: Hanya untuk memperjelas kasus penggunaan di sini: Saat ini saya menyimpan nomor dalam satu bidang varchar, dan saya meninggalkannya tepat saat pelanggan memasukkannya. Kemudian, ketika nomor tersebut dibutuhkan oleh kode, saya menormalkannya. Masalahnya adalah jika saya ingin menanyakan beberapa juta baris untuk menemukan nomor telepon yang cocok, ini melibatkan fungsi, seperti

where dbo.f_normalizenum(num1) = dbo.f_normalizenum(num2)

yang sangat tidak efisien. Juga kueri yang mencari hal-hal seperti kode area menjadi sangat rumit bila hanya berupa satu bidang varchar.

[Sunting]

Orang-orang telah memberikan banyak saran bagus di sini, terima kasih! Sebagai pembaruan, inilah yang saya lakukan sekarang: Saya masih menyimpan angka persis seperti yang dimasukkan, di bidang varchar, tetapi alih-alih menormalkan hal-hal pada waktu kueri, saya memiliki pemicu yang melakukan semua itu saat catatan dimasukkan atau diperbarui. Jadi saya memiliki ints atau bigints untuk setiap bagian yang perlu saya kueri, dan bidang tersebut diindeks untuk membuat kueri berjalan lebih cepat.

Eric Z Beard
sumber
Jawaban kontemporer untuk pertanyaan ini ada di sini - stackoverflow.com/a/51761170/968003 . Intinya - gunakan RFC 3966 untuk penyimpanan dan libphonenumber untuk parsing / validasi.
Alex Klaus

Jawaban:

80

Pertama, di luar kode negara, tidak ada standar yang sebenarnya. Hal terbaik yang dapat Anda lakukan adalah mengenali, berdasarkan kode negara, negara mana dari nomor telepon tertentu dan menangani sisa nomor tersebut sesuai dengan format negara tersebut.

Namun secara umum, peralatan telepon dan semacamnya distandarisasi sehingga Anda hampir selalu dapat memecah nomor telepon tertentu menjadi komponen berikut

  • C Kode negara 1-10 digit (sekarang 4 atau kurang, tetapi itu dapat berubah)
  • Kode Area (Provinsi / negara bagian / wilayah) kode 0-10 digit (mungkin sebenarnya menginginkan bidang wilayah dan bidang area secara terpisah, daripada satu kode area)
  • E Tukar (awalan, atau sakelar) kode 0-10 digit
  • Nomor baris L 1-10 digit

Dengan metode ini Anda berpotensi dapat memisahkan nomor sehingga Anda dapat menemukan, misalnya, orang yang mungkin dekat satu sama lain karena memiliki kode negara, wilayah, dan pertukaran yang sama. Dengan ponsel itu bukan lagi sesuatu yang bisa Anda andalkan.

Selanjutnya, di dalam setiap negara ada standar yang berbeda. Anda selalu dapat bergantung pada (AAA) EEE-LLLL di AS, tetapi di negara lain Anda mungkin memiliki pertukaran di kota-kota (AAA) EE-LLL, dan hanya nomor baris di daerah pedesaan (AAA) LLLL. Anda harus mulai dari atas pada pohon dari beberapa bentuk, dan memformatnya sesuai informasi yang Anda miliki. Misalnya, kode negara 0 memiliki format yang diketahui untuk sisa nomornya, tetapi untuk kode negara 5432 Anda mungkin perlu memeriksa kode areanya sebelum Anda memahami sisa nomornya.

Anda mungkin juga ingin menangani vanitynomor seperti (800) Lucky-Guy, yang memerlukan pengakuan bahwa, jika itu adalah nomor AS, ada satu digit terlalu banyak (dan Anda mungkin perlu representasi penuh untuk periklanan atau tujuan lain) dan bahwa di AS surat-surat itu dipetakan ke nomor berbeda dari di Jerman.

Anda mungkin juga ingin menyimpan seluruh nomor secara terpisah sebagai bidang teks (dengan internasionalisasi) sehingga Anda dapat kembali lagi nanti dan mengurai ulang nomor saat ada perubahan, atau sebagai cadangan jika seseorang mengirimkan metode yang buruk untuk mengurai format negara tertentu dan kehilangan informasi.

Adam Davis
sumber
1
Tahu validasi JavaScript yang bagus untuk mencoba dan memvalidasi ini?
cmcculloh
6
E164 menetapkan batas yang jauh lebih ketat untuk panjang nomor: 1-3 untuk negara, dan panjang maksimal 15. Ini tidak akan berubah dalam waktu dekat, karena mengetahui sistem telepon global.
Kaya
Panjang yang Anda tentukan tampaknya, menurut ITU-T E.164, sepenuhnya salah. Akan sangat membantu jika Anda dapat memposting tautan ke dokumen standar dari mana Anda memperoleh informasi, atau menjelaskan mengapa E.164 tidak berlaku.
Abtin Forouzandeh
5
@Abtin - tidak semua sistem telepon sesuai dengan ITU-T E.164. Namun, sebagian besar dari mereka melakukannya, dan ada baiknya mempertimbangkan pilihan antara mematuhi standar, dan mengunci beberapa orang atau melampaui apa yang dikatakan standar dan menerima semua orang. Perhatikan bahwa E.164 dapat dilihat sebagai bagian dari skema di atas. Namun, saya yakin format terbaik adalah apa pun yang dimasukkan pengguna dengan tepat, dan kemudian memiliki algoritme penguraian yang memberi tokenize saat diperlukan, daripada menyimpan formulir yang ditokenisasi dalam database.
Adam Davis
1) Dapatkah seseorang menganggap semua nomor internasional sesuai dengan memiliki komponen CAE? 2) Dapatkah Anda berasumsi bahwa komponen C adalah satu-satunya hal yang berbeda tergantung dari mana Anda melakukan panggilan. Misalnya nomor AS 850-555-1234 memiliki A = 850 dan E = 555-1234, lalu C = 1 jika menelepon dari AS, dan C = 001 jika menelepon dari Inggris. Intinya terlepas dari mana Anda menelepon, A dan E tidak dinamis dengan cara apa pun, benar?
AaronLS
55

KISS - Saya bosan dengan banyak situs web AS. Mereka memiliki beberapa kode yang ditulis dengan cerdik untuk memvalidasi kode pos dan nomor telepon. Ketika saya mengetikkan info kontak Norwegia saya yang benar-benar valid, saya menemukan bahwa cukup sering hal itu ditolak.

Biarkan sebagai string, kecuali Anda memiliki kebutuhan khusus untuk sesuatu yang lebih maju.

Bjorn Reppen
sumber
Seorang tua yang baik nvarchar(42)dengan sedikit validasi /^+?[0-9 -\.\(\)#*]{4,41}$/bekerja dengan sangat baik!
SandRock
Saya setuju, tetapi tidak setuju pada saat bersamaan. Umumnya Anda ingin melakukan sesuatu dengan nomor telepon yang disimpan itu seperti menampilkannya. Daripada melakukan cara ini untuk mencoba menguraikannya cukup untuk menampilkannya seperti yang Anda inginkan, saya lebih suka menyimpannya dengan cara yang dinormalisasi. Sekarang saya tidak mengatakan bahwa kita harus memaksakan tanda kurung di sekitar kode area. Apa yang saya katakan adalah bahwa itu semua angka tanpa tanda hubung dll.
The Muffin Man
4
Saya yakin nomor telepon harus diurai sebelum menyimpannya, sehingga dapat divalidasi dan disimpan dengan cara yang dinormalisasi. Parsing internasional dan pemformatan nomor telepon sangat mungkin dilakukan dengan googlei18n / libphonenumber .
Roel
21

The Wikipedia halaman di E.164 harus memberitahu Anda segala sesuatu yang perlu Anda ketahui.

Kaya
sumber
3
tidak, standar itu hanya menjelaskan bagaimana nomor telepon disusun (dibuat dari tiga nomor) tetapi tidak menentukan bagaimana nomor tersebut ditampilkan dan / atau disimpan. Apakah saya mengatakan standar? Maksud saya Rekomendasi .
BlueWizard
8

Inilah struktur yang saya usulkan, saya menghargai umpan balik:

Bidang database telepon harus berupa varchar (42) dengan format berikut:

CountryCode - Nomor x Ekstensi

Jadi, misalnya, di AS, kami dapat memiliki:

1-2125551234x1234

Ini akan mewakili nomor AS (kode negara 1) dengan kode area / nomor (212) 555 1234 dan ekstensi 1234.

Memisahkan kode negara dengan tanda hubung membuat kode negara jelas bagi seseorang yang membaca dengan teliti data. Ini tidak sepenuhnya diperlukan karena kode negara adalah " kode awalan " (Anda dapat membacanya dari kiri ke kanan dan Anda selalu dapat menentukan negaranya dengan jelas). Namun, karena kode negara memiliki panjang yang berbeda-beda (antara 1 dan 4 karakter saat ini), Anda tidak dapat dengan mudah mengetahui kode negara secara sekilas kecuali Anda menggunakan semacam pemisah.

Saya menggunakan "x" untuk memisahkan ekstensi karena jika tidak maka tidak akan mungkin (dalam banyak kasus) untuk mencari tahu mana nomornya dan mana yang merupakan ekstensi.

Dengan cara ini Anda dapat menyimpan seluruh nomor, termasuk kode negara dan ekstensi, dalam satu bidang database, yang kemudian dapat Anda gunakan untuk mempercepat kueri Anda, daripada bergabung pada fungsi yang ditentukan pengguna seperti yang telah Anda lakukan dengan susah payah sejauh ini. .

Mengapa saya memilih varchar (42)? Pertama-tama, nomor telepon internasional akan memiliki panjang yang bervariasi, oleh karena itu disebut "var". Saya menyimpan tanda hubung dan "x", jadi itu menjelaskan "char", dan bagaimanapun, Anda tidak akan melakukan aritmatika integer pada nomor telepon (saya kira) jadi tidak masuk akal untuk mencoba menggunakan tipe numerik . Adapun panjang 42, saya menggunakan panjang maksimum yang mungkin dari semua bidang yang dijumlahkan, berdasarkan jawaban Adam Davis, dan menambahkan 2 untuk tanda hubung dan 'x ".

tidak sengaja dikosongkan
sumber
7

Cari E.164. Pada dasarnya, Anda menyimpan nomor telepon sebagai kode yang dimulai dengan awalan negara dan akhiran pbx opsional. Tampilan kemudian menjadi masalah lokalisasi. Validasi juga dapat dilakukan, tetapi juga merupakan masalah lokalisasi (berdasarkan awalan negara).

Misalnya, + 12125551212 + 202 akan diformat dalam lokal en_US sebagai (212) 555-1212 x202. Ini akan memiliki format yang berbeda dalam en_GBatau de_DE.

Ada cukup banyak info di luar sana tentang ITU-T E.164, tetapi cukup samar.

jcoby
sumber
6

Saya pribadi menyukai gagasan untuk menyimpan nomor telepon varchar yang dinormalisasi (mis. 9991234567) kemudian, tentu saja, memformat nomor telepon itu sebaris saat Anda menampilkannya.

Dengan cara ini semua data dalam database Anda "bersih" dan bebas format

Mike Fielden
sumber
4

Penyimpanan

Simpan telepon di RFC 3966 (seperti +1-202-555-0252, +1-202-555-7166;ext=22). Perbedaan utama dari E.164 adalah

  • Tidak ada batasan panjangnya
  • Dukungan ekstensi

Untuk mengoptimalkan kinerja operasi tampilan, simpan telepon dalam format Nasional / Internasional di sebelah bidang RFC 3966.

Jangan simpan kode negara di bidang terpisah kecuali Anda memiliki alasan yang serius untuk itu. Mengapa? Karena Anda tidak boleh meminta kode negara di UI.

Kebanyakan, orang masuk ke telepon saat mereka mendengarnya. Misalnya jika format lokal akan dimulai dari 0atau 8, akan mengganggu pengguna untuk melakukan transformasi nomor di kepala (seperti, " OK, jangan ketik '0', pilih negara dan ketikkan sisanya kata orang di bidang ini ").

Parsing

Google mendukung Anda dan Anda dapat memvalidasi dan mengurai nomor telepon apa pun dengan menggunakan perpustakaan libphonenumber mereka . Ada port untuk hampir semua bahasa.

Jadi biarkan pengguna memasukkan " 0449053501" atau " 04 4905 3501" atau " (04) 4905 3501". Alat tersebut akan menentukan sisanya untuk Anda.

Lihat demo resminya , untuk mengetahui seberapa besar manfaatnya.

Alex Klaus
sumber
3

Mungkin menyimpan bagian nomor telepon di kolom yang berbeda, memungkinkan entri kosong atau nol?

Thomas Owens
sumber
3

Ok, jadi berdasarkan info di halaman ini, berikut adalah awal dari validator nomor telepon internasional:

function validatePhone(phoneNumber) {
    var valid = true;
    var stripped = phoneNumber.replace(/[\(\)\.\-\ \+\x]/g, '');    

    if(phoneNumber == ""){
        valid = false;
    }else if (isNaN(parseInt(stripped))) {
        valid = false;
    }else if (stripped.length > 40) {
        valid = false;
    }
    return valid;
}

Berdasarkan skrip dari halaman ini: http://www.webcheatsheet.com/javascript/form_validation.php

cmcculloh
sumber
2

Standar untuk memformat angka adalah e.164 , Anda harus selalu menyimpan angka dalam format ini. Anda tidak boleh mengizinkan nomor ekstensi di bidang yang sama dengan nomor telepon, itu harus disimpan secara terpisah. Adapun numerik vs alfanumerik, Itu tergantung pada apa yang akan Anda lakukan dengan data itu.

Brian West
sumber
1

Saya pikir teks bebas (mungkin varchar (25)) adalah standar yang paling banyak digunakan. Ini akan memungkinkan untuk format apa pun, baik domestik atau internasional.

Saya kira faktor pendorong utama mungkin adalah bagaimana tepatnya Anda menanyakan angka-angka ini dan apa yang Anda lakukan dengannya.

Mengenakan
sumber
Ini meleset dari inti pertanyaannya, yaitu untuk menstandarisasi konten kolom DB untuk memastikan pencocokan yang unik. Bagaimana cara memastikan bahwa ketika saya menanyakan nomor telepon 800-555-1212 yang cocok jika pengguna dapat memasukkan "(800) 555-1212", "+1.800.555.1212" atau nilai apa pun yang setara? Itulah tantangan yang sedang ditangani.
Irongaze.com
1

Saya menemukan sebagian besar formulir web dengan benar mengizinkan kode negara, kode area, lalu 7 digit sisanya tetapi hampir selalu lupa untuk mengizinkan masuknya ekstensi. Ini hampir selalu berakhir dengan membuat saya mengucapkan kata-kata marah, karena di tempat kerja kami tidak memiliki resepsionis, dan ext. # Diperlukan untuk menghubungi saya.

Aaron
sumber
1

Saya menemukan sebagian besar formulir web dengan benar mengizinkan kode negara, kode area, lalu 7 digit sisanya tetapi hampir selalu lupa untuk mengizinkan masuknya ekstensi. Ini hampir selalu berakhir dengan membuat saya mengucapkan kata-kata marah, karena di tempat kerja kami tidak memiliki resepsionis, dan ext. # Diperlukan untuk menghubungi saya.

Saya harus memeriksanya, tetapi menurut saya skema DB kami serupa. Kami memegang kode negara (mungkin default ke AS, tidak yakin), kode area, 7 digit, dan ekstensi.

Thomas Owens
sumber
1

Bagaimana dengan menyimpan kolom teks bebas yang menunjukkan versi nomor telepon yang mudah digunakan, lalu versi yang dinormalisasi yang menghilangkan spasi, tanda kurung, dan memperluas '+'. Sebagai contoh:

Ramah pengguna: +44 (0) 181 4642542

Dinormalisasi : 00441814642542

ColinYounger
sumber
10
Untuk siapa tepatnya +44 (0) 181 4642542 ramah? Pengguna Inggris yang mungkin tidak tahu apa yang harus dilakukan dengan +44 jika mereka tidak terbiasa melakukan panggilan internasional, atau pengguna internasional yang tidak tahu bahwa mereka seharusnya melepaskan (0)?
Mark Baker
0

Saya akan memilih bidang teks bebas dan bidang yang berisi versi numerik murni dari nomor telepon. Saya akan menyerahkan representasi nomor telepon kepada pengguna dan menggunakan bidang yang dinormalisasi khusus untuk perbandingan nomor telepon dalam aplikasi berbasis TAPI atau ketika mencoba menemukan entri ganda dalam direktori telepon. Tentu tidak ada salahnya memberikan pengguna skema entri yang menambahkan intelijen seperti bidang terpisah untuk kode negara (jika perlu), kode area, nomor pangkalan dan ekstensi.


sumber
0

Dari mana Anda mendapatkan nomor telepon? Jika Anda mendapatkannya dari bagian jaringan telepon, Anda akan mendapatkan serangkaian digit dan jenis nomor serta paket, mis

441234567890 tipe / rencana 0x11 (yang berarti E.164 internasional)

Dalam kebanyakan kasus, hal terbaik yang harus dilakukan adalah menyimpan semua ini sebagaimana adanya, dan menormalkan tampilan, meskipun menyimpan nomor yang dinormalisasi dapat berguna jika Anda ingin menggunakannya sebagai kunci unik atau serupa.

Mark Baker
sumber
0

Ramah pengguna: +44 (0) 181464 2542 dinormalisasi: 00441814642542

(0) tidak valid dalam format internasional. Lihat standar ITU-T E.123.

Format "dinormalisasi" tidak akan berguna bagi pembaca AS karena mereka menggunakan 011 untuk akses internasional.

penyanyi dave
sumber
0

Saya telah menggunakan 3 cara berbeda untuk menyimpan nomor telepon tergantung pada persyaratan penggunaan.

  1. Jika nomor tersebut disimpan hanya untuk pengambilan manusia dan tidak akan digunakan untuk mencari, nomor tersebut disimpan dalam bidang tipe string persis seperti yang dimasukkan pengguna.
  2. Jika field akan dicari maka karakter tambahan apapun, seperti +, spasi dan tanda kurung dll akan dihapus dan angka yang tersisa disimpan dalam field tipe string.
  3. Terakhir, jika nomor telepon akan digunakan oleh komputer / aplikasi telepon, maka dalam hal ini harus dimasukkan dan disimpan sebagai nomor telepon valid yang dapat digunakan oleh sistem, opsi ini tentu saja, menjadi yang paling sulit untuk dikodekan untuk.
Jimoc
sumber