Có tiêu chuẩn nào để lưu trữ số điện thoại chuẩn hóa trong cơ sở dữ liệu không?


95

Cấu trúc dữ liệu tốt để lưu trữ số điện thoại trong các trường cơ sở dữ liệu là gì? Tôi đang tìm thứ gì đó đủ linh hoạt để xử lý các số quốc tế và cũng là thứ cho phép các phần khác nhau của số được truy vấn một cách hiệu quả.

Chỉnh sửa: Chỉ để làm rõ trường hợp sử dụng ở đây: Tôi hiện lưu trữ các số trong một trường varchar duy nhất và tôi để chúng ngay khi khách hàng nhập chúng. Sau đó, khi cần mã số, tôi sẽ chuẩn hóa nó. Vấn đề là nếu tôi muốn truy vấn vài triệu hàng để tìm số điện thoại phù hợp, nó liên quan đến một hàm, như

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

mà không hiệu quả kinh khủng. Ngoài ra, các truy vấn đang tìm kiếm những thứ như mã vùng trở nên cực kỳ phức tạp khi nó chỉ là một trường varchar duy nhất.

[Biên tập]

Mọi người đã đưa ra rất nhiều đề xuất tốt ở đây, cảm ơn! Như một bản cập nhật, đây là những gì tôi đang làm bây giờ: Tôi vẫn lưu trữ các số chính xác như chúng đã được nhập, trong trường varchar, nhưng thay vì chuẩn hóa mọi thứ tại thời điểm truy vấn, tôi có một trình kích hoạt thực hiện tất cả những gì hoạt động khi các bản ghi được chèn vào hoặc cập nhật. Vì vậy, tôi có int hoặc bigint cho bất kỳ phần nào tôi cần truy vấn và những trường đó được lập chỉ mục để làm cho truy vấn chạy nhanh hơn.


Đây là câu trả lời đương đại cho câu hỏi - stackoverflow.com/a/51761170/968003 . Ý chính của nó - sử dụng RFC 3966 để lưu trữ và libphonenumber để phân tích cú pháp / xác thực.
Alex Klaus

Câu trả lời:


80

Đầu tiên, ngoài mã quốc gia, không có tiêu chuẩn thực sự nào. Về điều tốt nhất bạn có thể làm là nhận ra, theo mã quốc gia, một số điện thoại cụ thể thuộc về quốc gia nào và xử lý phần còn lại của số theo định dạng của quốc gia đó.

Tuy nhiên, nói chung, thiết bị điện thoại và những thứ như vậy được tiêu chuẩn hóa nên hầu như bạn luôn có thể chia một số điện thoại nhất định thành các thành phần sau

  • C Mã quốc gia từ 1-10 chữ số (hiện có 4 chữ số trở xuống, nhưng điều đó có thể thay đổi)
  • Mã vùng (Tỉnh / tiểu bang / vùng) mã 0-10 chữ số (thực tế có thể muốn trường vùng và trường vùng riêng biệt, thay vì một mã vùng)
  • E Exchange (tiền tố hoặc chuyển đổi) mã 0-10 chữ số
  • L Dòng số 1-10 chữ số

Với phương pháp này, bạn có khả năng tách các số để bạn có thể tìm, chẳng hạn như những người có thể ở gần nhau vì họ có cùng quốc gia, khu vực và mã trao đổi. Với điện thoại di động không còn là thứ mà bạn có thể tin tưởng.

Hơn nữa, bên trong mỗi quốc gia có những tiêu chuẩn khác nhau. Bạn luôn có thể phụ thuộc vào EEE-LLLL (AAA) ở Hoa Kỳ, nhưng ở một quốc gia khác, bạn có thể có các sàn giao dịch ở các thành phố (AAA) EE-LLL và chỉ đơn giản là số dòng ở các vùng nông thôn (AAA) LLLL. Bạn sẽ phải bắt đầu ở trên cùng trong một dạng cây nào đó và định dạng chúng khi bạn có thông tin. Ví dụ: mã quốc gia 0 có định dạng đã biết cho phần còn lại của số, nhưng đối với mã quốc gia 5432, bạn có thể cần phải kiểm tra mã vùng trước khi hiểu phần còn lại của số.

Bạn cũng có thể muốn xử lý các vanitysố, chẳng hạn như (800) Lucky-Guy, đòi hỏi phải nhận ra rằng, nếu đó là số của Hoa Kỳ, có quá nhiều chữ số (và bạn có thể cần phải đại diện đầy đủ cho quảng cáo hoặc các mục đích khác) và ở Hoa Kỳ, các chữ cái liên kết với số khác với ở Đức.

Bạn cũng có thể muốn lưu trữ toàn bộ số riêng biệt dưới dạng trường văn bản (với quốc tế hóa) để bạn có thể quay lại sau và phân tích lại các số khi mọi thứ thay đổi hoặc để dự phòng trong trường hợp ai đó gửi một phương pháp không hợp lệ để phân tích định dạng của một quốc gia cụ thể và mất thông tin.


1
Biết bất kỳ xác thực JavaScript tốt nào để thử và xác thực điều này?
cmcculloh 4/10/08

6
E164 đặt ra các giới hạn nghiêm ngặt hơn nhiều về độ dài của các số: 1-3 cho các quốc gia và độ dài tối đa là 15. Điều này sẽ không sớm thay đổi, nếu biết hệ thống điện thoại toàn cầu.
Phong phú

Độ dài bạn đã chỉ định dường như hoàn toàn sai, theo ITU-T E.164. Sẽ rất hữu ích nếu bạn có thể đăng một liên kết đến tài liệu tiêu chuẩn mà từ đó bạn lấy thông tin của mình hoặc giải thích lý do tại sao E.164 không áp dụng.
Abtin Forouzandeh

5
@Abtin - không phải mọi hệ thống điện thoại đều tuân thủ ITU-T E.164. Tuy nhiên, phần lớn trong số họ đều làm như vậy, và thật đáng giá khi cân nhắc lựa chọn giữa việc tuân thủ các tiêu chuẩn và khóa một số người ra ngoài hoặc vượt ra ngoài những gì tiêu chuẩn nói và chấp nhận tất cả mọi người. Lưu ý rằng E.164 có thể được xem như một tập con của lược đồ trên. Tuy nhiên, tôi tin rằng định dạng tốt nhất là bất kỳ thứ gì người dùng nhập chính xác và sau đó có một thuật toán phân tích cú pháp để mã hóa nó khi cần thiết, thay vì lưu trữ biểu mẫu được mã hóa trong cơ sở dữ liệu.
Adam Davis

1) Người ta có thể giả định rằng tất cả các số quốc tế đều tuân theo các thành phần CAE không? 2) Bạn có thể giả định rằng thành phần C là thành phần duy nhất khác nhau tùy thuộc vào nơi bạn đang quay số. Ví dụ: số 850-555-1234 của Hoa Kỳ có A = 850 và E = 555-1234, sau đó C = 1 nếu quay số từ Hoa Kỳ và C = 001 nếu quay số từ Vương quốc Anh. Cho dù bạn đang quay số từ đâu, A và E đều không động theo bất kỳ cách nào, đúng không?
AaronLS

55

KISS - Tôi cảm thấy mệt mỏi với nhiều trang web của Hoa Kỳ. Họ có một số mã được viết khéo léo để xác nhận mã bưu điện và số điện thoại. Khi tôi nhập thông tin liên hệ Na Uy hoàn toàn hợp lệ của mình, tôi thấy rằng nó thường bị từ chối.

Hãy để nó thành một chuỗi, trừ khi bạn có một số nhu cầu cụ thể về một thứ gì đó cao cấp hơn.


Một cái cũ tốt nvarchar(42)với một chút xác thực /^+?[0-9 -\.\(\)#*]{4,41}$/hoạt động rất tốt!
SandRock

Tôi đồng ý, nhưng đồng thời không đồng ý. Nói chung, bạn muốn làm điều gì đó với số điện thoại được lưu trữ đó chẳng hạn như hiển thị nó. Thay vì cố gắng phân tích cú pháp đủ để hiển thị nó theo cách bạn muốn, tôi muốn lưu trữ nó theo cách chuẩn hóa. Bây giờ tôi không nói rằng chúng ta nên đi xa để thực thi dấu ngoặc đơn xung quanh mã vùng. Những gì tôi đang nói là tất cả đều là những con số không có dấu gạch ngang, v.v.
The Muffin Man,

4
Tôi tin rằng các số điện thoại nên được phân tích cú pháp trước khi lưu trữ, để chúng có thể được xác thực và lưu trữ theo cách chuẩn hóa. Việc phân tích cú pháp và định dạng số điện thoại quốc tế là hoàn toàn có thể thực hiện được với googlei18n / libphonenumber .
Roel

21

Các trang Wikipedia trên E.164 nên nói với bạn mọi thứ bạn cần biết.


3
không, tiêu chuẩn đó chỉ xác định cách số điện thoại được cấu trúc (chúng được tạo từ ba số) nhưng nó không chỉ định cách chúng được hiển thị và / hoặc lưu trữ. Tôi đã nói chuẩn chưa? Ý tôi là Đề xuất .
BlueWizard

8

Đây là cấu trúc đề xuất của tôi, tôi đánh giá cao phản hồi:

Trường cơ sở dữ liệu điện thoại phải là một varchar (42) với định dạng sau:

Mã quốc gia - Số x Phần mở rộng

Vì vậy, ví dụ, ở Hoa Kỳ, chúng tôi có thể có:

1-2125551234x1234

Số này đại diện cho một số Hoa Kỳ (mã quốc gia 1) với mã vùng / số (212) 555 1234 và số máy lẻ 1234.

Việc tách mã quốc gia ra bằng dấu gạch ngang giúp mã quốc gia rõ ràng đối với người đang xem xét dữ liệu. Điều này không hoàn toàn cần thiết vì mã quốc gia là " mã tiền tố " (bạn có thể đọc chúng từ trái sang phải và bạn sẽ luôn có thể xác định quốc gia một cách rõ ràng). Tuy nhiên, vì mã quốc gia có độ dài khác nhau (từ 1 đến 4 ký tự tại thời điểm này) nên bạn không thể dễ dàng nhận ra mã quốc gia trong nháy mắt trừ khi bạn sử dụng một số loại dấu phân tách.

Tôi sử dụng dấu "x" để phân tách phần mở rộng bởi vì nếu không thì thực sự không thể (trong nhiều trường hợp) để tìm ra đâu là số và đâu là phần mở rộng.

Bằng cách này, bạn có thể lưu trữ toàn bộ số, bao gồm mã quốc gia và phần mở rộng, trong một trường cơ sở dữ liệu duy nhất, sau đó bạn có thể sử dụng để tăng tốc các truy vấn của mình, thay vì tham gia vào một hàm do người dùng xác định như bạn vẫn làm cho đến nay .

Tại sao tôi chọn varchar (42)? Trước hết, số điện thoại quốc tế sẽ có độ dài khác nhau, do đó là "var". Tôi đang lưu trữ một dấu gạch ngang và một "x", để giải thích cho "char", và dù sao, bạn sẽ không thực hiện phép tính số nguyên trên các số điện thoại (tôi đoán vậy), vì vậy, việc cố gắng sử dụng một loại số sẽ không có ý nghĩa gì . Đối với độ dài 42, tôi đã sử dụng độ dài tối đa có thể của tất cả các trường được cộng lại, dựa trên câu trả lời của Adam Davis và thêm 2 cho dấu gạch ngang và 'x ".


7

Tra cứu E.164. Về cơ bản, bạn lưu trữ số điện thoại dưới dạng mã bắt đầu bằng tiền tố quốc gia và hậu tố pbx tùy chọn. Hiển thị sau đó là một vấn đề bản địa hóa. Việc xác thực cũng có thể được thực hiện, nhưng đó cũng là vấn đề bản địa hóa (dựa trên tiền tố quốc gia).

Ví dụ: + 12125551212 + 202 sẽ được định dạng trong ngôn ngữ en_US là (212) 555-1212 x202. Nó sẽ có một định dạng khác trong en_GBhoặc de_DE.

Có khá nhiều thông tin về ITU-T E.164, nhưng nó khá khó hiểu.


6

Cá nhân tôi thích ý tưởng lưu trữ một số điện thoại varchar chuẩn hóa (ví dụ: 9991234567), sau đó, tất nhiên, định dạng nội dòng số điện thoại đó khi bạn hiển thị nó.

Bằng cách này, tất cả dữ liệu trong cơ sở dữ liệu của bạn là "sạch" và không có định dạng


4

Lưu trữ

Lưu trữ điện thoại trong RFC 3966 (như +1-202-555-0252, +1-202-555-7166;ext=22). Sự khác biệt chính so với E.164

  • Không giới hạn độ dài
  • Hỗ trợ các tiện ích mở rộng

Để tối ưu hóa hiệu suất của các thao tác xem, hãy lưu điện thoại ở định dạng Quốc gia / Quốc tế bên cạnh trường RFC 3966.

Không lưu mã quốc gia trong một trường riêng biệt trừ khi bạn có lý do nghiêm trọng cho việc đó. Tại sao? Bởi vì bạn không nên hỏi mã quốc gia trên giao diện người dùng.

Hầu hết, mọi người vào điện thoại khi họ nghe thấy chúng. Ví dụ: nếu định dạng cục bộ sẽ bắt đầu từ 0hoặc 8, sẽ gây khó chịu cho người dùng khi thực hiện chuyển đổi số trong đầu (như " OK, không nhập '0', hãy chọn quốc gia và nhập phần còn lại của người nói trong lĩnh vực này ").

Phân tích cú pháp

Google hỗ trợ bạn và bạn có thể xác thực và phân tích cú pháp bất kỳ số điện thoại nào bằng cách sử dụng thư viện libphonenumber của họ . Có các cổng cho hầu hết mọi ngôn ngữ.

Vì vậy, hãy để người dùng chỉ cần nhập " 0449053501" hoặc " 04 4905 3501" hoặc " (04) 4905 3501". Công cụ sẽ tìm ra phần còn lại cho bạn.

Hãy xem bản demo chính thức để biết nó hữu ích như thế nào.


3

Có lẽ lưu trữ các phần số điện thoại trong các cột khác nhau, cho phép các mục nhập trống hoặc rỗng?


3

Được rồi, dựa trên thông tin trên trang này, đây là phần bắt đầu về trình xác thực số điện thoại quốc tế:

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

Dựa trên một tập lệnh từ trang này một cách lỏng lẻo: http://www.webcheatsheet.com/javascript/form_validation.php


2

Tiêu chuẩn để định dạng số là e.164 , Bạn nên luôn lưu trữ các số ở định dạng này. Bạn không bao giờ được phép để số máy nhánh trong cùng trường với số điện thoại, chúng nên được lưu trữ riêng biệt. Đối với số và chữ và số, nó phụ thuộc vào những gì bạn sẽ làm với dữ liệu đó.


1

Tôi nghĩ văn bản tự do (có thể là varchar (25)) là tiêu chuẩn được sử dụng rộng rãi nhất. Điều này sẽ cho phép bất kỳ định dạng nào, trong nước hoặc quốc tế.

Tôi đoán yếu tố thúc đẩy chính có thể là bạn đang truy vấn chính xác những con số này như thế nào và bạn đang làm gì với chúng.


Điều này bỏ sót điểm của câu hỏi, đó là chuẩn hóa nội dung của các trường DB để đảm bảo khớp duy nhất. Làm cách nào để đảm bảo rằng khi tôi truy vấn số điện thoại 800-555-1212 rằng số này khớp nếu người dùng có thể nhập "(800) 555-1212", "+1.800.555.1212" hoặc bất kỳ giá trị tương đương nào khác? Đó là thách thức đang được giải quyết.
Irongaze.com

1

Tôi thấy hầu hết các biểu mẫu web cho phép chính xác mã quốc gia, mã vùng, sau đó là 7 chữ số còn lại nhưng hầu như luôn quên cho phép nhập phần mở rộng. Điều này hầu như luôn khiến tôi thốt ra những lời tức giận, vì tại nơi làm việc, chúng tôi không có lễ tân và số máy lẻ # của tôi là cần thiết để liên hệ với tôi.


1

Tôi thấy hầu hết các biểu mẫu web cho phép chính xác mã quốc gia, mã vùng, sau đó là 7 chữ số còn lại nhưng hầu như luôn quên cho phép nhập phần mở rộng. Điều này hầu như luôn khiến tôi thốt ra những lời tức giận, vì tại nơi làm việc, chúng tôi không có lễ tân và số máy lẻ # của tôi là cần thiết để liên hệ với tôi.

Tôi sẽ phải kiểm tra, nhưng tôi nghĩ rằng lược đồ DB của chúng tôi cũng tương tự. Chúng tôi giữ mã quốc gia (có thể mặc định là Hoa Kỳ, không chắc chắn), mã vùng, 7 chữ số và phần mở rộng.


1

Còn về việc lưu trữ một cột freetext hiển thị phiên bản số điện thoại thân thiện với người dùng, sau đó là phiên bản chuẩn hóa loại bỏ dấu cách, dấu ngoặc và mở rộng '+'. Ví dụ:

Thân thiện với người dùng: +44 (0) 181 4642542

Chuẩn hóa: 00441814642542


10
Chính xác thì +44 (0) 181 4642542 là để thân thiện với ai? Người dùng Vương quốc Anh có thể không biết phải làm gì với +44 nếu họ không quen gọi điện quốc tế hoặc người dùng quốc tế sẽ không biết rằng họ phải bỏ dấu (0)?
Mark Baker

0

Tôi sẽ tìm trường văn bản tự do và trường chứa phiên bản số hoàn toàn của số điện thoại. Tôi sẽ để phần trình bày số điện thoại cho người dùng và sử dụng trường chuẩn hóa đặc biệt để so sánh số điện thoại trong các ứng dụng dựa trên TAPI hoặc khi cố gắng tìm các mục nhập kép trong danh bạ điện thoại. Tất nhiên, việc cung cấp cho người dùng một lược đồ nhập cảnh bổ sung thông tin chi tiết như các trường riêng biệt cho mã quốc gia (nếu cần), mã vùng, số cơ sở và tiện ích mở rộng sẽ không gây hại cho người dùng.


0

Bạn lấy số điện thoại từ đâu? Nếu bạn đang nhận chúng từ một phần của mạng điện thoại, bạn sẽ nhận được một chuỗi các chữ số, một loại số và gói, ví dụ:

441234567890 loại / gói 0x11 (có nghĩa là E.164 quốc tế)

Trong hầu hết các trường hợp, điều tốt nhất cần làm là lưu trữ tất cả những số này như chúng vốn có và chuẩn hóa để hiển thị, mặc dù việc lưu trữ các số chuẩn hóa có thể hữu ích nếu bạn muốn sử dụng chúng làm khóa duy nhất hoặc tương tự.


0

Người dùng thân thiện: +44 (0) 181 464 2542 chuẩn hóa: 00441814642542

(0) không hợp lệ ở định dạng quốc tế. Xem tiêu chuẩn ITU-T E.123.

Định dạng "chuẩn hóa" sẽ không hữu ích cho người đọc Hoa Kỳ vì họ sử dụng 011 để truy cập quốc tế.


0

Tôi đã sử dụng 3 cách khác nhau để lưu số điện thoại tùy theo yêu cầu sử dụng.

  1. Nếu số đang được lưu trữ chỉ để con người truy xuất và sẽ không được sử dụng để tìm kiếm nó được lưu trữ trong trường loại chuỗi chính xác như người dùng đã nhập.
  2. Nếu trường sẽ được tìm kiếm thì bất kỳ ký tự thừa nào, chẳng hạn như +, dấu cách và dấu ngoặc vuông, v.v. sẽ bị xóa và số còn lại được lưu trữ trong trường loại chuỗi.
  3. Cuối cùng, nếu số điện thoại sẽ được sử dụng bởi một ứng dụng máy tính / điện thoại, thì trong trường hợp này, nó sẽ cần được nhập và lưu trữ dưới dạng số điện thoại hợp lệ có thể sử dụng được bởi hệ thống, tất nhiên tùy chọn này là khó mã nhất cho.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.