正規化された電話番号をデータベースに保存するための標準はありますか?


95

データベースフィールドに電話番号を格納するための適切なデータ構造は何ですか?国際番号を処理するのに十分な柔軟性があるもの、および番号のさまざまな部分を効率的に照会できるものを探しています。

編集:ユースケースをここで明確にするために:私は現在、単一のvarcharフィールドに数値を格納し、顧客が入力したとおりに数値を残しています。次に、コードで番号が必要な場合は、正規化します。問題は、数百万行をクエリして一致する電話番号を検索する場合、次のような関数が含まれることです。

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

これはひどく非効率的です。また、市外局番などを検索するクエリは、varcharフィールドが1つだけの場合、非常に扱いにくくなります。

[編集]

人々はここでたくさんの良い提案をしました、ありがとう!更新として、これが私が今行っていることです:数値を入力されたとおりにvarcharフィールドに格納しますが、クエリ時に物事を正規化する代わりに、レコードが挿入されるときにすべての機能を実行するトリガーがありますまたは更新されました。したがって、クエリを実行する必要のある部分にはintまたはbigintsがあり、これらのフィールドにはインデックスが付けられており、クエリをより高速に実行できます。


質問に対する現代的な答えはここにあります-stackoverflow.com/a/51761170/968003。その要点-ストレージにはRFC 3966を、構文解析/検証にはlibphonenumberを使用してください。
Alex Klaus

回答:


80

まず、国コードを超えて、実際の標準はありません。あなたができる最善のことは、国コードによって、特定の国の電話番号がどの国に属しているかを認識し、その国の形式に従って残りの番号を処理することです。

ただし、一般に電話機器などは標準化されているため、ほとんどの場合、特定の電話番号を次のコンポーネントに分割できます。

  • C国コード1〜10桁(現時点では4以下ですが、変更される場合があります)
  • エリアコード(州/州/地域)コード0-10桁(実際には、1つのエリアコードではなく、地域フィールドとエリアフィールドを別々に必要とする場合があります)
  • E交換(プレフィックス、またはスイッチ)コード0-10桁
  • L行番号1から10桁

この方法を使用すると、たとえば、同じ国、地域、および交換コードを持っているために互いに近い可能性がある人々を見つけることができるように、番号を分離することができます。もはやあなたが頼りにできるものではなくなった携帯電話で。

さらに、各国では異なる基準があります。米国では常に(AAA)EEE-LLLLに依存できますが、別の国では、都市(AAA)EE-LLLで交換を行い、農村地域(AAA)LLLLで単純に回線番号を使用する場合があります。何らかの形のツリーの一番上から始めて、情報があるようにフォーマットする必要があります。たとえば、国コード0の残りの番号の形式は既知ですが、国コード5432の場合、残りの番号を理解する前に市外局番を調べる必要がある場合があります。

vanityような番号を処理することもできます(800) Lucky-Guy。これは、米国の番号の場合、桁数が多すぎること(および広告やその他の目的で完全な表現が必要な場合がある)、および米国では文字がドイツとは異なる数字。

また、数値全体をテキストフィールド(国際化対応)として個別に保存して、後で戻って、物事が変化したときに数値を再解析したり、誰かが特定の国の形式を解析するための悪い方法を提出した場合のバックアップとして使用したりすることもできます。情報を失います。


1
これを試して検証するための良いJavaScript検証を知っていますか?
cmcculloh 2008年

6
E164は、番号の長さに対してはるかに厳しい制限を設定しています。国の場合は1〜3、最大長は15です。これは、グローバルテレフォニーシステムを知っているため、すぐには変更されません。
リッチ

指定した長さは、ITU-T E.164に従って、完全に間違っているようです。情報を引き出すための標準ドキュメントへのリンクを投稿したり、E.164が適用されない理由を説明したりすると役立つでしょう。
Abtin Forouzandeh 2009

5
@Abtin-すべての電話システムがITU-T E.164に準拠しているわけではありません。しかし、それらの大多数はそうです。そして、標準に準拠するか、一部の人々を締め出すか、標準が言うことを超えて全員を受け入れるかの選択を比較検討する価値があります。E.164は、上記のスキームのサブセットと見なすことができることに注意してください。それでも、最適な形式はユーザーが正確に入力したものであり、トークン化されたフォームをデータベースに保存するのではなく、必要に応じて構文解析アルゴリズムでトークン化します。
アダムデイビス

1)すべての国際番号がCAEコンポーネントを持つことに準拠していると想定できますか?2)どこからダイヤルするかによってCコンポーネントだけが異なると思いますか?たとえば、米国の番号850-555-1234にはA = 850とE = 555-1234があり、米国からダイヤルする場合はC = 1、英国からダイヤルする場合はC = 001です。どこからダイヤルしているかに関係なく、AとEは動的ではありません、そうですか?
AaronLS 2016年

55

KISS-米国のWebサイトの多くに飽きてきました。彼らは郵便番号と電話番号を検証するための巧妙に書かれたコードをいくつか持っています。完全に有効なノルウェーの連絡先情報を入力すると、拒否されることがよくあります。

より高度なものが必要な場合を除いて、文字列のままにします。


nvarchar(42)少し検証を行った古き良きものは/^+?[0-9 -\.\(\)#*]{4,41}$/とてもうまくいきます!
SandRock 2012

私は同意しますが、同時に同意しません。一般的には、表示されている電話番号など、保存されている電話番号を使って何かをしたいとします。正規化された方法で保存したい方法を表示するために十分に解析しようとするこの道をたどるのではなく、市外局番をかっこで囲む必要があると言っているのではありません。私が言っていることは、それはすべての数字ダッシュなしなどだということである
マフィンマン

4
電話番号を保存する前に解析して、正規化された方法で検証および保存できるようにすべきだと思います。電話番号の国際的な解析とフォーマットは、googlei18n / libphonenumberで完全に可能です
Roel

21

E.164Wikipediaページに、知っておくべきすべての情報が記載されています。


3
いいえ、その規格は電話番号の構成方法を定義しているだけです(3つの番号で構成されています)が、これらの表示方法や格納方法は指定されていません。標準って言った?私は勧告を意味しました。
BlueWizard 2017

8

これが提案された構造です。フィードバックをいただければ幸いです。

電話データベースフィールドは、次の形式のvarchar(42)である必要があります。

国コード-番号x内線番号

したがって、たとえば、米国では次のようになります。

1-2125551234x1234

これは、地域コード/番号(212)555 1234および内線番号1234を使用する米国の番号(国コード1)を表します。

国コードをダッシュ​​で区切ると、データを閲覧している人に国コードが明確になります。国コードは「プレフィックスコード」であるため、これは厳密には必要ありません(左から右に読むことができ、いつでも国を明確に決定することができます)。ただし、国コードの長さはさまざまです(現時点では1文字から4文字まで)。なんらかの区切り記号を使用しないと、国コードを一目で簡単に判別できません。

"x"を使用して内線番号を区切ります。そうしないと、(多くの場合)どちらが番号でどれが内線番号であるかを実際に判別することが不可能になるためです。

このようにして、国コードと内線番号を含む整数全体を単一のデータベースフィールドに格納できます。これを使用して、これまで苦労して行っていたユーザー定義関数に参加する代わりに、クエリを高速化できます。 。

なぜvarchar(42)を選んだのですか?まず、国際電話番号はさまざまな長さになるため、「var」になります。私はダッシュと「x」を格納しているので、「char」を説明しています。とにかく、電話番号に対して整数演算を行うことはないので(おそらく)、数値型を使用するのはほとんど意味がありません。 。42の長さについては、Adam Davisの回答に基づいて合計されたすべてのフィールドの可能な最大長を使用し、ダッシュと「x」に2を追加しました。


7

E.164を検索します。基本的に、電話番号は国のプレフィックスとオプションのpbxサフィックスで始まるコードとして保存します。表示はローカリゼーションの問題です。検証も可能ですが、ローカリゼーションの問題でもあります(国の接頭辞に基づく)。

たとえば、+ 12125551212 + 202は、en_USロケールでは(212)555-1212 x202としてフォーマットされます。en_GBまたはでは形式が異なりますde_DE

ITU-T E.164についてはかなりの情報がありますが、それはかなり謎めいています。


6

個人的には、正規化されたvarcharの電話番号(たとえば、9991234567)を保存し、表示するときにその電話番号をインラインでフォーマットするのが好きです。

これにより、データベース内のすべてのデータが「クリーン」になり、フォーマットが不要になります


4

ストレージ

保管して電話RFC 3966(のような+1-202-555-0252+1-202-555-7166;ext=22)。E.164との主な違いは

  • 長さに制限はありません
  • 拡張機能のサポート

ビュー操作のパフォーマンスを最適化するには、電話をRFC 3966フィールドの横にあるNational / International形式で保存します。

深刻な理由がない限り、国コードを別のフィールドに保存しないでください。どうして?UIで国コードを尋ねるべきではないからです。

ほとんどの場合、人々は彼らがそれらを聞くと、電話に入ります。たとえば、ローカル形式が0やから始まる場合、8ユーザーが頭の中で数値変換を行うのは面倒です(たとえば、「OK、「0」を入力しないで、国を選択して、人はこの分野で言った ")。

解析中

グーグルはあなたの背中を持っている、そしてあなたは彼らのlibphonenumberライブラリーを使うことでどんな電話番号でも検証して、分析することができる。ほとんどすべての言語へのポートがあります。

したがって、ユーザーに " 0449053501"または " 04 4905 3501"または " (04) 4905 3501"と入力してもらいます。ツールが残りを計算します。

参照してください公式のデモを助けそれをしないどのくらいの感覚を得るために、。



3

では、このページの情報に基づいて、国際電話番号バリデーターのスタートです:

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

大まかにこのページのスクリプトに基づいています:http : //www.webcheatsheet.com/javascript/form_validation.php


2

数値のフォーマットの標準はe.164です。常にこの形式で数値を格納する必要があります。電話番号と同じフィールドに内線番号を許可しないでください。これらは個別に保存する必要があります。数値と英数字については、そのデータをどのように処理するかによって異なります。


1

フリーテキスト(たぶんvarchar(25))が最も広く使われている標準だと思います。これにより、国内または海外のあらゆる形式が可能になります。

主な原動力は、これらの数値をどの程度正確に照会しているか、そしてそれらをどのように処理しているかにあると思います。


これは、一意の一致を保証するためにDBフィールドの内容を標準化するという質問の要点を逃しています。電話番号800-555-1212をクエリするときに、ユーザーが「(800)555-1212」、「+ 1.800.555.1212」、またはその他の同等の値を入力できるかどうかを確認するにはどうすればよいですか?それが対処されている課題です。
Irongaze.com 2016年

1

ほとんどのWebフォームでは、国コード、市外局番、残りの7桁が正しく許可されていますが、ほとんどの場合、内線番号の入力を忘れています。仕事では受付係がいないので、これはほとんどいつも私に怒りの言葉を発することになります、そして私に連絡するために私の内線番号が必要です。


1

ほとんどのWebフォームでは、国コード、市外局番、残りの7桁が正しく許可されていますが、ほとんどの場合、内線番号の入力を忘れています。仕事では受付係がいないので、これはほとんどいつも私に怒りの言葉を発することになります、そして私に連絡するために私の内線番号が必要です。

確認する必要がありますが、DBスキーマも同様だと思います。国コード(デフォルトは米国である可能性がありますが、わかりません)、市外局番、7桁、および内線番号を保持しています。


1

使いやすいバージョンの電話番号を表示するフリーテキスト列を格納してから、スペース、角かっこを削除して「+」を展開した正規化バージョンを格納するのはどうでしょう。例えば:

ユーザーフレンドリー: +44(0)181 4642542

正規化: 00441814642542


10
+44(0)181 4642542は、誰のために意図されているのですか?国際電話をかけることに慣れていない場合に+44をどうすればよいかわからない英国のユーザー、または(0)をドロップすることになっていることを知らない国際的なユーザー?
Mark Ba​​ker、

0

フリーテキストフィールドと、電話番号の純粋に数値のバージョンを含むフィールドに移動します。私は電話番号の表現をユーザーに任せ、TAPIベースのアプリケーションで電話番号を比較する場合、または電話帳で二重のエントリを見つけようとする場合に、正規化されたフィールドを使用します。もちろん、国コード(必要な場合)、市外局番、基本番号、および内線番号の個別のフィールドなどのインテリジェンスを追加する入力スキームをユーザーに提供することは害になりません。


0

電話番号はどこから取得していますか?あなたが電話ネットワークの一部からそれらを取得している場合は、数字の文字列と数値のタイプと計画を取得します、例えば

441234567890タイプ/プラン0x11(つまり、国際的なE.164)

ほとんどの場合、これらすべてをそのまま保存し、正規化して表示することをお勧めします。ただし、正規化された数値を保存すると、一意のキーなどとして使用する場合に役立ちます。


0

ユーザーフレンドリー:+44(0)181 464 2542正規化:00441814642542

(0)は、国際形式では無効です。ITU-T E.123標準を参照してください。

「正規化された」形式は、国際的なアクセスに011を使用するため、米国の読者には役立ちません。


0

私は、使用要件に応じて、3つの異なる方法で電話番号を保存しました。

  1. 数値が人間の検索のためだけに保存​​されており、ユーザーが入力したとおりに文字列型フィールドに保存されている数値を検索するために使用されない場合。
  2. フィールドが検索される場合、+、スペース、角かっこなどの余分な文字は削除され、残りの数値は文字列型フィールドに格納されます。
  3. 最後に、電話番号がコンピューター/電話アプリケーションで使用される場合、この場合、システムで使用できる有効な電話番号として入力および保存する必要があります。もちろん、このオプションはコーディングが最も困難です。ために。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.