Normalleştirilmiş telefon numaralarını bir veritabanında saklamak için bir standart var mı?


96

Telefon numaralarını veritabanı alanlarında saklamak için iyi bir veri yapısı nedir? Uluslararası numaraları işlemek için yeterince esnek ve aynı zamanda sayının çeşitli kısımlarının verimli bir şekilde sorgulanmasına izin veren bir şey arıyorum.

Düzenleme: Sadece burada kullanım örneğini açıklığa kavuşturmak için: Şu anda numaraları tek bir varchar alanında saklıyorum ve onları müşterinin girdiği gibi bırakıyorum. Daha sonra kod tarafından sayıya ihtiyaç duyulduğunda normalize ediyorum. Sorun şu ki, eşleşen telefon numaralarını bulmak için birkaç milyon satırı sorgulamak istersem, bunun gibi bir işlevi içerir.

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

ki bu çok verimsiz. Ayrıca alan kodu gibi şeyleri arayan sorgular, yalnızca tek bir varchar alanı olduğunda son derece zor hale gelir.

[Düzenle]

İnsanlar burada çok iyi önerilerde bulundu, teşekkürler! Bir güncelleme olarak şu anda yaptığım şey şu: Numaraları tam olarak girildikleri gibi bir varchar alanında saklıyorum, ancak her şeyi sorgu zamanında normalleştirmek yerine, kayıtlar eklendikçe tüm bunları yapan bir tetikleyicim var veya güncellendi. Bu yüzden, sorgulamam gereken herhangi bir parça için ints veya bigints var ve bu alanlar sorguların daha hızlı çalışmasını sağlamak için indeksleniyor.


Soruya çağdaş bir cevap burada - stackoverflow.com/a/51761170/968003 . İşin özü - depolama için RFC 3966 ve ayrıştırma / doğrulama için libphonenumber kullanın.
Alex Klaus

Yanıtlar:


81

Birincisi, ülke kodunun ötesinde gerçek bir standart yoktur. Yapabileceğiniz en iyi şey, belirli bir telefon numarasının hangi ülkeye ait olduğunu ülke koduna göre tanımak ve numaranın geri kalanını o ülkenin formatına göre ele almaktır.

Bununla birlikte, genel olarak, telefon ekipmanı ve benzeri standartlaştırılmıştır, böylece belirli bir telefon numarasını neredeyse her zaman aşağıdaki bileşenlere ayırabilirsiniz.

  • C Ülke kodu 1-10 hane (şu anda 4 veya daha az, ancak bu değişebilir)
  • Alan kodu (İl / eyalet / bölge) 0-10 basamaklı kod (aslında bir alan kodu yerine ayrı ayrı bir bölge alanı ve alan alanı isteyebilir)
  • E Değişim (önek veya anahtar) kodu 0-10 basamaklı
  • L Satır numarası 1-10 hane

Bu yöntemle, örneğin aynı ülke, bölge ve değişim kodlarına sahip oldukları için birbirine yakın olabilecek kişileri bulabileceğiniz şekilde potansiyel olarak sayıları ayırabilirsiniz. Artık güvenebileceğiniz bir şey olmayan cep telefonlarıyla.

Dahası, her ülkenin içinde farklı standartlar vardır. ABD'de her zaman bir (AAA) EEE-LLLL'ye güvenebilirsiniz, ancak başka bir ülkede şehirlerde (AAA) EE-LLL ve kırsal alanlardaki (AAA) LLLL satır numaralarınız olabilir. En tepeden bir ağaçta başlamanız ve bilginiz olduğu gibi biçimlendirmeniz gerekecek. Örneğin, 0 ülke kodu, numaranın geri kalanı için bilinen bir biçime sahiptir, ancak 5432 ülke kodu için, numaranın geri kalanını anlamadan önce alan kodunu incelemeniz gerekebilir.

Ayrıca işlemek isteyebilirsiniz vanitygibi sayıları (800) Lucky-Guybir Amerikan sayı ise, orada (ve reklam veya başka amaçlarla tam temsil gerekebilir) bir çok hanesi ve ABD'de harfler eşlemek olduğunu, kabul ederek gerektirir ki, Almanya'dakinden farklı rakamlar.

Numaranın tamamını ayrı bir metin alanı olarak (uluslararasılaştırma ile) ayrı olarak depolamak isteyebilirsiniz, böylece daha sonra geri dönüp işler değiştikçe numaraları yeniden ayrıştırabilir veya birisinin belirli bir ülkenin biçimini ayrıştırmak için kötü bir yöntem sunması durumunda yedek olarak kullanabilirsiniz. ve bilgileri kaybeder.


1
Bunu denemek ve doğrulamak için iyi bir JavaScript doğrulaması biliyor musunuz?
cmcculloh

6
E164, numaraların uzunluğuna çok daha katı sınırlar koyar: ülkeler için 1-3 ve maksimum 15 uzunluk. Küresel telefon sistemi bilindiğinde, bu yakın zamanda değişmeyecektir.
Zengin

ITU-T E.164'e göre belirlediğiniz uzunluklar tamamen yanlış görünüyor. Bilgilerinizi aldığınız standartlar belgesine bir bağlantı göndermeniz veya E.164'ün neden geçerli olmadığını açıklamanız faydalı olacaktır.
Abtin Forouzandeh

5
@Abtin - her telefon sistemi ITU-T E.164 ile uyumlu değildir. Bununla birlikte, büyük çoğunluğu bunu yapıyor ve standartlara uygun olma ile bazı insanları dışarıda bırakma veya standardın söylediğinin ötesine geçme ve herkesi kabul etme arasındaki seçimi tartmaya değer. E.164'ün yukarıdaki şemanın bir alt kümesi olarak görülebileceğini unutmayın. Yine de, en iyi formatın, kullanıcının tam olarak girdiği şey olduğuna inanıyorum ve daha sonra, belirteçli formu veritabanında depolamak yerine, gerektiğinde bunu belirtecek bir ayrıştırma algoritmasına sahibim.
Adam Davis

1) Tüm uluslararası numaraların CAE bileşenlerine uygun olduğu varsayılabilir mi? 2) C bileşeninin, nereden aradığınıza bağlı olarak farklı olan tek şey olduğunu varsayabilir misiniz? Örneğin ABD numarası 850-555-1234, A = 850 ve E = 555-1234'e sahiptir ve daha sonra ABD'den arama yapılıyorsa C = 1 ve İngiltere'den arama yapılıyorsa C = 001'dir. Nereden çevirdiğinizden bağımsız olarak, A ve E hiçbir şekilde dinamik değil, değil mi?
AaronLS

55

KISS - ABD'deki birçok web sitesinden sıkılmaya başladım. Posta kodlarını ve telefon numaralarını doğrulamak için akıllıca yazılmış bazı kodları vardır. Tamamen geçerli Norveççe iletişim bilgilerimi yazdığımda, çoğu zaman reddedildiğini görüyorum.

Daha gelişmiş bir şeye özel bir ihtiyaç duymadıkça onu bir dize olarak bırakın.


nvarchar(42)Biraz onaylanmış iyi bir yaşlı /^+?[0-9 -\.\(\)#*]{4,41}$/çok iyi çalışıyor!
Sandrock

Katılıyorum ama aynı zamanda katılmıyorum. Genellikle, bu kayıtlı telefon numarasıyla onu görüntülemek gibi bir şeyler yapmak istersiniz. Onu istediğiniz gibi göstermek için yeterince ayrıştırmaya çalışmaktan ziyade normalleştirilmiş bir şekilde saklamayı tercih ederim. Şimdi, alan kodunun etrafına parantez koymaya kadar gitmemiz gerektiğini söylemiyorum. Demek istediğim, bunların hepsi sayılar, tire vs.
The Muffin Man

4
Telefon numaralarının normalleştirilmiş bir şekilde doğrulanması ve depolanması için saklanmadan önce ayrıştırılması gerektiğine inanıyorum. Telefon numaralarının uluslararası ayrıştırılması ve biçimlendirilmesi googlei18n / libphonenumber ile mükemmel bir şekilde mümkündür .
Roel

21

E.164 Wikipedia sayfası size bilmeniz gereken her şeyi anlatmalı.


3
hayır, bu standart sadece telefon numaralarının nasıl yapılandırıldığını tanımlar (üç numaradan oluşurlar) ancak bunların nasıl görüntüleneceğini ve / veya saklanacağını belirtmez. Standart mı dedim? Tavsiye demek istedim .
BlueWizard

8

İşte önerilen yapım, geri bildirim almaktan memnuniyet duyarım:

Telefon veritabanı alanı, aşağıdaki biçime sahip bir varchar (42) olmalıdır:

CountryCode - Sayı x Uzantı

Yani, örneğin ABD'de, sahip olabilirdik:

1-2125551234x1234

Bu, alan kodu / numarası (212) 555 1234 ve dahili 1234 olan bir ABD numarasını (ülke kodu 1) temsil eder.

Ülke kodunu bir kısa çizgi ile ayırmak, ülke kodunu verileri inceleyen biri için anlaşılır hale getirir. Ülke kodları " önek kodları " olduğundan bu kesinlikle gerekli değildir (bunları soldan sağa okuyabilir ve ülkeyi her zaman net bir şekilde belirleyebilirsiniz). Ancak, ülke kodlarının farklı uzunlukları olduğundan (şu anda 1 ile 4 karakter arasında), bir tür ayırıcı kullanmadığınız sürece ülke kodunu bir bakışta kolayca anlayamazsınız.

Uzantıyı ayırmak için bir "x" kullanıyorum çünkü aksi takdirde (çoğu durumda) hangi numaranın ve hangisinin uzantı olduğunu bulmak gerçekten mümkün olmazdı.

Bu şekilde, ülke kodu ve dahili numara da dahil olmak üzere tüm numarayı tek bir veritabanı alanında saklayabilir ve daha sonra şu ana kadar acı verici bir şekilde yaptığınız gibi kullanıcı tanımlı bir işleve katılmak yerine sorgularınızı hızlandırmak için kullanabilirsiniz. .

Neden bir varchar seçtim (42)? Öncelikle, uluslararası telefon numaraları çeşitli uzunluklarda olacak, dolayısıyla "var" olacaktır. Bir tire ve bir "x" saklıyorum, bu "karakter" i açıklıyor ve yine de, telefon numaralarında tamsayı aritmetiği yapmayacaksınız (sanırım) bu yüzden sayısal bir tür kullanmayı denemek biraz mantıklı geliyor . 42 uzunluğuna gelince, Adam Davis'in cevabına göre eklenen tüm alanların mümkün olan maksimum uzunluğunu kullandım ve tire ve "x" için 2 ekledim.


7

E.164'ü arayın. Temel olarak, telefon numarasını ülke ön eki ve isteğe bağlı bir pbx son eki ile başlayan bir kod olarak kaydedersiniz. Bu durumda ekran bir yerelleştirme sorunudur. Doğrulama da yapılabilir, ancak bu aynı zamanda bir yerelleştirme sorunudur (ülke önekine göre).

Örneğin, + 12125551212 + 202, en_US yerel ayarında (212) 555-1212 x202 olarak biçimlendirilir. en_GBVeya biçiminde farklı bir biçime sahip olacaktır de_DE.

ITU-T E.164 hakkında oldukça fazla bilgi var, ancak oldukça şifreli.


6

Ben kişisel olarak normalleştirilmiş bir varchar telefon numarası kaydetme (örneğin 9991234567) ve ardından, bu telefon numarasını görüntülerken satır içi olarak biçimlendirme fikrini seviyorum.

Bu şekilde, veritabanınızdaki tüm veriler "temiz" olur ve biçimlendirme içermez


4

Depolama

Saklayın telefonlar RFC 3966 (gibi +1-202-555-0252, +1-202-555-7166;ext=22). Temel fark E. 164 vardır

  • Uzunlukta sınır yok
  • Uzantı desteği

Görüntüleme işlemlerinin performansını optimize etmek için telefonu, RFC 3966 alanının yanında Ulusal / Uluslararası biçimde saklayın.

Bunun için ciddi bir nedeniniz olmadıkça ülke kodunu ayrı bir alanda saklamayın. Neden? Çünkü kullanıcı arayüzünde ülke kodunu sormamalısınız.

Çoğunlukla insanlar telefonları duydukça girerler. Örneğin, yerel formattan başlayacaksa 0veya 8kullanıcının kafasından sayı dönüşümünü yapması can sıkıcı olacaktır (" Tamam," 0 "yazmayın, ülkeyi seçin ve geri kalanını yazın. kişi bu alanda ") dedi .

Ayrıştırma

Google arkanızda ve libphonenumber kitaplığını kullanarak herhangi bir telefon numarasını doğrulayabilir ve ayrıştırabilirsiniz . Hemen hemen her dilde bağlantı noktaları vardır.

Öyleyse kullanıcının " 0449053501" veya " 04 4905 3501" veya " (04) 4905 3501" girmesine izin verin . Araç gerisini sizin için çözecektir.

Ne kadar yardımcı olduğuna dair bir fikir edinmek için resmi demoya bakın .


3

Belki de telefon numarası bölümlerini farklı sütunlarda depolamak, boş veya boş girişlere izin vermek?


3

Tamam, bu sayfadaki bilgilere göre, işte uluslararası bir telefon numarası doğrulayıcı için bir başlangıç:

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;
}

Bu sayfadaki bir komut dosyasına genel olarak dayalı: http://www.webcheatsheet.com/javascript/form_validation.php


2

Numaraları formatlama standardı e.164'tür . Numaraları her zaman bu formatta saklamalısınız . Dahili numaranın telefon numarası ile aynı alanda olmasına asla izin vermemelisiniz, bunlar ayrı olarak saklanmalıdır. Sayısal vs alfanümerik gelince, bu verilerle ne yapacağınıza bağlıdır.


1

Bence serbest metin (belki varchar (25)) en yaygın kullanılan standarttır. Bu, yerel veya uluslararası herhangi bir formata izin verecektir.

Sanırım ana itici faktör, bu sayıları tam olarak nasıl sorguladığınız ve onlarla ne yaptığınız olabilir.


Bu, benzersiz eşleşmeyi sağlamak için DB alanlarının içeriğini standartlaştırmak olan sorunun amacını kaçırmaktadır. 800-555-1212 numaralı telefonu sorguladığımda, kullanıcının "(800) 555-1212", "+1.800.555.1212" veya başka bir eşdeğer değer girip giremeyeceğinden nasıl emin olabilirim? Ele alınan zorluk bu.
Irongaze.com

1

Çoğu web formunun ülke kodu, alan kodu ve ardından kalan 7 haneye doğru bir şekilde izin verdiğini, ancak neredeyse her zaman bir uzantı girişine izin vermeyi unuttuğunu görüyorum. Bu neredeyse her zaman bana kızgın sözler söylememe neden oluyor, çünkü işte resepsiyon görevlimiz yok ve bana ulaşmak için dahili numaram gerekiyor.


1

Çoğu web formunun ülke kodu, alan kodu ve ardından kalan 7 haneye doğru bir şekilde izin verdiğini, ancak neredeyse her zaman bir uzantı girişine izin vermeyi unuttuğunu görüyorum. Bu neredeyse her zaman bana kızgın sözler söylememe neden oluyor, çünkü işte resepsiyon görevlimiz yok ve bana ulaşmak için dahili numaram gerekiyor.

Kontrol etmem gerekecek ama DB şemamızın benzer olduğunu düşünüyorum. Bir ülke kodu (varsayılan olarak ABD olabilir, kesin değil), alan kodu, 7 basamak ve dahili numaramız var.


1

Telefon numarasının kullanıcı dostu bir versiyonunu gösteren bir serbest metin sütunu, ardından boşlukları, köşeli parantezleri kaldıran ve '+' genişleten normalleştirilmiş bir sürümü depolamaya ne dersiniz? Örneğin:

Kullanıcı dostu: +44 (0) 181 4642542

Normalleştirilmiş: 00441814642542


10
+44 (0) 181 4642542 tam olarak kimin için dosttur? Uluslararası aramaya alışkın değillerse +44 ile ne yapacaklarını bilemeyebilecek Birleşik Krallık kullanıcıları veya (0) 'ı bırakmaları gerektiğini bilmeyen uluslararası kullanıcılar?
Mark Baker

0

Bir serbest metin alanına ve telefon numarasının tamamen sayısal bir versiyonunu içeren bir alana giderdim. Telefon numarasının temsilini kullanıcıya bırakırdım ve normalleştirilmiş alanı özellikle TAPI tabanlı uygulamalarda telefon numarası karşılaştırmaları için veya bir telefon rehberinde çift giriş bulmaya çalışırken kullanırdım. Elbette, kullanıcıya ülke kodu (gerekirse), alan kodu, baz numarası ve dahili numara için ayrı alanlar gibi zeka ekleyen bir giriş şeması sağlamaktan zarar gelmez.


0

Telefon numaralarını nereden alıyorsun? Bunları telefon ağının bir kısmından alıyorsanız, bir dizi rakam ve bir numara türü ve planı alırsınız, örn.

441234567890 tip / plan 0x11 (uluslararası E.164 anlamına gelir)

Çoğu durumda yapılacak en iyi şey, bunların tümünü olduğu gibi saklamak ve ekran için normalleştirmektir, ancak normalleştirilmiş sayıları depolamak, bunları benzersiz bir anahtar veya benzeri olarak kullanmak istiyorsanız yararlı olabilir.


0

Kullanıcı dostu: +44 (0) 181464 2542 normalleştirilmiş: 00441814642542

(0) uluslararası formatta geçerli değildir. ITU-T E.123 standardına bakın.

"Normalleştirilmiş" format, uluslararası erişim için 011 kullandıklarından ABD okuyucular için yararlı olmayacaktır.


0

Kullanım gereksinimlerine bağlı olarak telefon numaralarını saklamak için 3 farklı yol kullandım.

  1. Numara yalnızca insan tarafından geri çağrılmak üzere saklanıyorsa ve tam olarak kullanıcının girdiği gibi bir dize türü alanında saklanan numarayı aramak için kullanılmayacaksa.
  2. Alan aranacaksa, +, boşluklar ve köşeli parantezler vb. Gibi ekstra karakterler kaldırılır ve kalan sayı bir dize türü alanında saklanır.
  3. Son olarak, telefon numarası bir bilgisayar / telefon uygulaması tarafından kullanılacaksa, bu durumda sistem tarafından kullanılabilen geçerli bir telefon numarası olarak girilmesi ve saklanması gerekecektir, bu seçenek elbette kodlanması en zor olanıdır. için.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.