정규화 된 전화 번호를 데이터베이스에 저장하는 표준이 있습니까?


95

데이터베이스 필드에 전화 번호를 저장하기위한 좋은 데이터 구조는 무엇입니까? 국제 전화 번호를 처리 할 수있을만큼 유연하고 번호의 다양한 부분을 효율적으로 쿼리 할 수있는 것을 찾고 있습니다.

편집 : 여기서 사용 사례를 명확히하기 위해 현재 단일 varchar 필드에 숫자를 저장하고 고객이 입력 한 그대로 둡니다. 그런 다음 코드에서 번호가 필요하면 정규화합니다. 문제는 일치하는 전화 번호를 찾기 위해 수백만 개의 행을 쿼리하려는 경우 다음과 같은 기능이 포함된다는 것입니다.

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

매우 비효율적입니다. 또한 지역 번호와 같은 것을 찾는 쿼리는 단일 varchar 필드 일 때 매우 까다로워집니다.

[편집하다]

사람들은 여기에서 좋은 제안을 많이했습니다. 감사합니다! 업데이트로 지금 내가하고있는 작업은 다음과 같습니다. 입력 한 그대로 숫자를 varchar 필드에 저장하지만 쿼리시 항목을 정규화하는 대신 레코드가 삽입 될 때 모든 작업을 수행하는 트리거가 있습니다. 또는 업데이트되었습니다. 따라서 쿼리해야하는 모든 부분에 대한 int 또는 bigint가 있으며 이러한 필드는 쿼리를 더 빠르게 실행하기 위해 인덱싱됩니다.


질문에 대한 현대적인 대답은 여기에 있습니다 -stackoverflow.com/a/51761170/968003 . 요점-저장에는 RFC 3966을 사용하고 구문 분석 / 검증에는 libphonenumber를 사용하십시오.
Alex Klaus

답변:


80

첫째, 국가 코드 외에는 실제 표준이 없습니다. 최선의 방법은 특정 전화 번호가 속한 국가를 국가 코드로 인식하고 해당 국가의 형식에 따라 나머지 번호를 처리하는 것입니다.

그러나 일반적으로 전화 장비 등은 표준화되어 있으므로 거의 항상 주어진 전화 번호를 다음 구성 요소로 나눌 수 있습니다.

  • C 국가 코드 1 ~ 10 자리 (현재 4 자리 이하이지만 변경 될 수 있음)
  • 지역 번호 (지방 / 주 / 지역) 코드 0-10 자리 (실제로 하나의 지역 번호가 아닌 지역 필드와 지역 필드가 별도로 필요할 수 있음)
  • E 교환 (접두사 또는 스위치) 코드 0-10 자리
  • L 라인 번호 1-10 자리

이 방법을 사용하면 국가, 지역 및 교환 코드가 같기 때문에 서로 가까운 사람을 찾을 수 있도록 잠재적으로 번호를 구분할 수 있습니다. 더 이상 의지 할 수없는 휴대 전화로.

또한 각 국가마다 다른 표준이 있습니다. 미국에서는 항상 (AAA) EEE-LLLL에 의존 할 수 있지만, 다른 국가에서는 도시 (AAA) EE-LLL에서 교환이 가능하고 농촌 지역 (AAA) LLLL에서는 단순히 줄 번호가있을 수 있습니다. 어떤 형식의 트리에서 맨 위에서 시작하여 정보가있는대로 형식을 지정해야합니다. 예를 들어, 국가 코드 0에는 나머지 번호에 대해 알려진 형식이 있지만 국가 코드 5432의 경우 나머지 번호를 이해하기 전에 지역 번호를 검사해야 할 수 있습니다.

또한 미국 번호 인 경우 하나의 숫자가 너무 많고 (광고 또는 기타 목적을 위해 전체 표현이 필요할 수 있음) 미국에서는 문자가 해당 문자에 매핑된다는 사실을 인식해야하는 vanity등의 숫자 를 처리 (800) Lucky-Guy할 수 있습니다. 독일과는 다릅니다.

전체 번호를 텍스트 필드 (국제화 포함)로 별도로 저장하여 나중에 돌아가서 상황이 변경 될 때 번호를 다시 구문 분석하거나 누군가가 특정 국가의 형식을 구문 분석하는 잘못된 방법을 제출하는 경우 백업으로 사용할 수도 있습니다. 정보를 잃습니다.


1
이것을 시도하고 유효성을 검사하는 좋은 JavaScript 유효성 검사를 알고 있습니까?
cmcculloh

6
E164는 번호 길이에 대해 훨씬 더 엄격한 제한을 설정합니다. 국가의 경우 1-3 개, 최대 길이는 15 개입니다. 이는 글로벌 전화 시스템을 알고 있으므로 조만간 변경되지 않을 것입니다.
Rich

지정한 길이는 ITU-T E.164에 따라 완전히 잘못된 것 같습니다. 정보를 추출한 표준 문서에 대한 링크를 게시하거나 E.164가 적용되지 않는 이유를 설명 할 수 있다면 도움이 될 것입니다.
Abtin Forouzandeh

5
@Abtin-모든 전화 시스템이 ITU-T E.164를 준수하는 것은 아닙니다. 그러나 대다수는 표준을 준수하는 것과 일부 사람들을 가두거나 표준이 말하는 것 이상으로 나아가고 모든 사람을 받아들이는 것 사이의 선택을 고려할 가치가 있습니다. E.164는 위 체계의 하위 집합으로 볼 수 있습니다. 그래도 가장 좋은 형식은 사용자가 정확하게 입력 한 다음 데이터베이스에 토큰 화 된 형식을 저장하는 대신 필요할 때 구문 분석 알고리즘을 사용하여 토큰 화하는 것입니다.
Adam Davis

1) 모든 국제 번호가 CAE 구성 요소를 준수한다고 가정 할 수 있습니까? 2) 어디에서 전화를 거는 지에 따라 C 구성 요소가 다른 유일한 것이라고 생각할 수 있습니까? 예를 들어 미국 번호 850-555-1234는 A = 850 및 E = 555-1234이고 미국에서 전화를 거는 경우 C = 1, 영국에서 전화를 거는 경우 C = 001입니다. 어디에서 전화를 거는 지에 관계없이 A와 E는 어떤 식 으로든 동적이지 않습니다. 맞습니까?
AaronLS

55

KISS-많은 미국 웹 사이트가 지겨워지고 있습니다. 그들은 우편 번호와 전화 번호를 확인하기 위해 영리하게 작성된 코드를 가지고 있습니다. 완벽하게 유효한 노르웨이 연락처 정보를 입력 할 때 자주 거부되는 것을 발견합니다.

좀 더 고급에 대한 특별한 필요가 없다면 문자열로 남겨 두십시오.


nvarchar(42)약간의 유효성 검사가있는 좋은 노인 /^+?[0-9 -\.\(\)#*]{4,41}$/은 매우 잘 작동합니다!
SandRock 2012

동의하지만 동시에 동의하지 않습니다. 일반적으로 저장된 전화 번호로 표시하는 것과 같은 작업을 수행합니다. 당신이 원하는 방식으로 그것을 보여줄만큼 충분히 파싱하려고 노력하는이 길을 따라 가기보다는 오히려 정규화 된 방식으로 저장하고 싶습니다. 이제 지역 번호를 괄호로 묶어야한다는 말은 아닙니다. 무슨 말인지는 더 대시 등 모든 수 없습니다이다
머핀 맨

4
전화 번호를 저장하기 전에 파싱해야하므로 정규화 된 방식으로 유효성을 검사하고 저장할 수 있습니다. googlei18n / libphonenumber를 사용하면 전화 번호의 국제 구문 분석 및 형식 지정이 완벽하게 가능합니다 .
Roel

21

E.164Wikipedia 페이지는 알아야 할 모든 것을 알려줍니다.


3
아니요,이 표준은 전화 번호가 구조화되는 방식 (3 개의 숫자로 구성됨)을 정의 할뿐 표시 및 / 또는 저장 방법을 지정하지 않습니다. 내가 표준이라고 했나요? 나는 추천을 의미했다 .
BlueWizard

8

제안 된 구조는 다음과 같습니다. 피드백에 감사드립니다.

전화 데이터베이스 필드는 다음 형식의 varchar (42) 여야합니다.

CountryCode-번호 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 필드 옆에 국가 / 국제 형식으로 전화기를 저장하십시오.

심각한 이유가없는 한 별도의 필드에 국가 코드를 저장하지 마십시오. 왜? UI에서 국가 코드를 묻지 말아야하기 때문입니다.

대부분 사람들은 들리는대로 전화기에 들어갑니다. 예를 들어 로컬 형식이 0또는로 시작 8하는 경우 사용자가 머리에서 숫자 변환을 수행하는 것이 성 가실 것입니다 (예 : " 좋아, '0'을 입력하지 말고 국가를 선택하고 나머지 사람이이 분야에서 말했다 ").

파싱

Google이 귀하를 지원하고 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

1

대부분의 웹 양식은 국가 코드, 지역 코드, 나머지 7 자리 숫자를 올바르게 허용하지만 거의 항상 내선 번호 입력을 허용하는 것을 잊어 버립니다. 직장에는 접수 원이없고 내 내선 번호가 필요하기 때문에 거의 항상 화가 난 말을하게됩니다.


1

대부분의 웹 양식은 국가 코드, 지역 코드, 나머지 7 자리 숫자를 올바르게 허용하지만 거의 항상 내선 번호 입력을 허용하는 것을 잊어 버립니다. 직장에는 접수 원이없고 내 내선 번호가 필요하기 때문에 거의 항상 화가 난 말을하게됩니다.

확인해야하는데 DB 스키마가 비슷하다고 생각합니다. 국가 코드 (기본값은 미국이지만 확실하지 않음), 지역 코드, 7 자리, 내선 번호가 있습니다.


1

사용자에게 친숙한 버전의 전화 번호를 표시하는 자유 텍스트 열을 저장 한 다음 공백, 대괄호를 제거하고 '+'를 확장하는 정규화 된 버전을 저장하는 것은 어떻습니까? 예를 들면 :

사용자 친화적 : +44 (0) 181 4642542

정규화 : 00441814642542


10
+44 (0) 181 4642542는 정확히 누구를 위해 우호적이어야합니까? 해외로 전화를 거는 데 익숙하지 않은 경우 +44로 무엇을해야할지 모르는 영국 사용자 또는 (0)을 떨어 뜨려야한다는 사실을 모르는 해외 사용자?
Mark Baker

0

나는 자유 텍스트 필드와 순수한 숫자 버전의 전화 번호를 포함하는 필드를 사용합니다. 전화 번호 표현은 사용자에게 맡기고 TAPI 기반 애플리케이션에서 전화 번호 비교를 위해 또는 전화 번호부에서 이중 항목을 찾으려고 할 때 특별히 정규화 된 필드를 사용합니다. 물론 국가 번호 (필요한 경우), 지역 번호, 기본 번호 및 내선에 대한 별도의 필드와 같은 정보를 추가하는 입력 체계를 사용자에게 제공하는 것은 문제가되지 않습니다.


0

전화 번호는 어디서 얻나요? 전화 네트워크의 일부에서 가져 오는 경우 숫자 문자열과 숫자 유형 및 계획을 받게됩니다.

441234567890 유형 / 계획 0x11 (국제 E.164를 의미 함)

대부분의 경우 가장 좋은 방법은이 모든 것을 그대로 저장하고 표시를 위해 정규화하는 것입니다. 그러나 정규화 된 숫자를 저장하는 것이 고유 키 또는 이와 유사한 것으로 사용하려는 경우 유용 할 수 있습니다.


0

사용자 친화적 : +44 (0) 181 464 2542 정규화 : 00441814642542

(0)은 국제 형식으로 유효하지 않습니다. ITU-T E.123 표준을 참조하십시오.

"정규화 된"형식은 미국 독자들에게 유용하지 않을 것입니다. 그들은 국제적인 접근을 위해 011을 사용하기 때문입니다.


0

사용 요구 사항에 따라 전화 번호를 저장하는 세 가지 방법을 사용했습니다.

  1. 번호가 사람이 검색하기 위해 저장되고 사용자가 입력 한 것과 정확히 일치하는 문자열 유형 필드에 저장된 번호를 검색하는 데 사용되지 않는 경우.
  2. 필드를 검색 할 경우 +, 공백 및 대괄호와 같은 추가 문자가 제거되고 나머지 숫자는 문자열 유형 필드에 저장됩니다.
  3. 마지막으로 전화 번호가 컴퓨터 / 전화 애플리케이션에서 사용되는 경우이 경우 시스템에서 사용할 수있는 유효한 전화 번호로 입력하고 저장해야합니다. 물론이 옵션은 코딩하기 가장 어렵습니다. 에 대한.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.