Điều gì sẽ là kiểu dữ liệu phù hợp để lưu trữ địa chỉ email trong PostgreSQL?
Tôi có thể sử dụng varchar
(hoặc thậm chí text
), nhưng tôi tự hỏi liệu có loại dữ liệu cụ thể hơn cho email không.
Điều gì sẽ là kiểu dữ liệu phù hợp để lưu trữ địa chỉ email trong PostgreSQL?
Tôi có thể sử dụng varchar
(hoặc thậm chí text
), nhưng tôi tự hỏi liệu có loại dữ liệu cụ thể hơn cho email không.
Câu trả lời:
DOMAIN
sTôi không nghĩ sử dụng citext
(không phân biệt chữ hoa chữ thường) là đủ [1] . Sử dụng PostgreQuery, chúng ta có thể tạo một miền tùy chỉnh về cơ bản là một số ràng buộc được xác định đối với một loại . Chúng ta có thể tạo một tên miền chẳng hạn qua citext
loại hoặc hơn text
.
type=email
thông số HTML5Hiện tại câu trả lời đúng nhất cho câu hỏi địa chỉ email là gì được chỉ định trong RFC5322 . Thông số kỹ thuật đó cực kỳ phức tạp [2] , đến nỗi mọi thứ phá vỡ nó. HTML5 chứa một thông số kỹ thuật khác nhau cho email ,
Yêu cầu này là vi phạm cố ý RFC 5322, định nghĩa cú pháp cho các địa chỉ email đồng thời quá nghiêm ngặt (trước ký tự "@"), quá mơ hồ (sau ký tự "@") và quá lỏng lẻo (cho phép nhận xét , các ký tự khoảng trắng và các chuỗi trích dẫn trong cách cư xử không quen thuộc với hầu hết người dùng) sẽ được sử dụng thực tế ở đây. [...] Biểu thức chính quy tương thích với JavaScript và Perl sau đây là cách triển khai định nghĩa trên.
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
Đây có thể là những gì bạn muốn và nếu nó đủ tốt cho HTML5, thì nó có thể đủ tốt cho bạn. Chúng ta có thể sử dụng điều đó trực tiếp trong PostgreSQL. Tôi cũng sử dụng citext
ở đây (về mặt kỹ thuật có nghĩa là bạn có thể đơn giản là regex một chút trực quan bằng cách loại bỏ chữ hoa hoặc chữ thường).
CREATE EXTENSION citext;
CREATE DOMAIN email AS citext
CHECK ( value ~ '^[a-zA-Z0-9.!#$%&''*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$' );
Bây giờ bạn có thể làm ...
SELECT 'asdf@foobar.com'::email;
Nhưng không
SELECT 'asdf@foob,,ar.com'::email;
SELECT 'asd@f@foobar.com'::email;
Bởi vì cả hai trở về
ERROR: value for domain email violates check constraint "email_check"
Bởi vì điều này cũng dựa trên citext
SELECT 'asdf@foobar.com'::email = 'ASdf@fooBAR.com';
trả về đúng theo mặc định.
plperlu
/Email::Valid
Là một lưu ý quan trọng, có một phương pháp chính xác hơn để làm điều này phức tạp hơn nhiều bằng cách sử dụng plperlu
. Nếu bạn cần mức độ chính xác này, bạn không muốn citext
. Email::Valid
thậm chí có thể kiểm tra xem tên miền có bản ghi MX không (ví dụ trong tài liệu của Email :: Hợp lệ)! Đầu tiên, thêm plperlu (yêu cầu siêu người dùng).
CREATE EXTENSION plperlu;
Sau đó tạo hàm , thông báo chúng tôi đánh dấu là IMMUTABLE
:
CREATE FUNCTION valid_email(text)
RETURNS boolean
LANGUAGE plperlu
IMMUTABLE LEAKPROOF STRICT AS
$$
use Email::Valid;
my $email = shift;
Email::Valid->address($email) or die "Invalid email address: $email\n";
return 'true';
$$;
Sau đó tạo miền ,
CREATE DOMAIN validemail AS text NOT NULL
CONSTRAINT validemail_check CHECK (valid_email(VALUE));
citext
là sai kỹ thuật. SMTP được định nghĩa local-part
là trường hợp nhạy cảm. Nhưng, một lần nữa, đây là một trường hợp thông số kỹ thuật là ngu ngốc. Nó chứa các cuộc khủng hoảng bản sắc riêng của nó. Thông số kỹ thuật cho biết local-part
(phần trước @
) "CÓ THỂ phân biệt chữ hoa chữ thường" ... "PHẢI được coi là phân biệt chữ hoa chữ thường" ... và "khai thác độ nhạy trường hợp của các bộ phận cục bộ hộp thư cản trở khả năng tương tác và không được khuyến khích."Cả hai biểu thức này đều thực thi giới hạn độ dài đối với địa chỉ email tổng thể hoặc phần cục bộ hoặc tên miền. RFC 5322 không chỉ định bất kỳ giới hạn độ dài. Những điều đó xuất phát từ những hạn chế trong các giao thức khác như giao thức SMTP để thực sự gửi email. RFC 1035 tuyên bố rằng các tên miền phải có 63 ký tự trở xuống, nhưng không bao gồm tên miền trong đặc tả cú pháp của nó. Lý do là một ngôn ngữ thông thường thực sự có thể thực thi giới hạn độ dài và không cho phép các dấu gạch nối liên tiếp cùng một lúc.
a-z
và A-Z
trong các lớp nhân vật?
~
bạn phải (a) sử dụng ~*
chữ không phân biệt chữ hoa chữ thường hoặc (b) có chữ hoa và chữ thường trong lớp char.
citext
Tôi ~
dường như không nhạy cảm với tôi, đó là lý do tại sao tôi hỏi.
Tôi luôn luôn sử dụng CITEXT
cho email, bởi vì một địa chỉ email là (trong thực tế) trường hợp không nhạy cảm , tức là John@Example.com giống như john@example.com.
Cũng dễ dàng hơn để thiết lập một chỉ mục duy nhất để ngăn ngừa trùng lặp, so với văn bản:
-- citext
CREATE TABLE address (
id serial primary key,
email citext UNIQUE,
other_stuff json
);
-- text
CREATE TABLE address (
id serial primary key,
email text,
other_stuff json
);
CREATE UNIQUE INDEX ON address ((lower(email)));
So sánh email cũng dễ dàng hơn và ít bị lỗi hơn:
SELECT * FROM address WHERE email = 'JOHN@example.com';
so với:
SELECT * FROM address WHERE lower(email) = lower('JOHN@example.com');
CITEXT
là một loại được xác định trong một mô-đun mở rộng tiêu chuẩn có tên là "citext" và có sẵn bằng cách gõ:
CREATE EXTENSION citext;
PS text
và varchar
hầu như giống nhau trong Postgres và không có hình phạt cho việc sử dụng text
như người ta có thể mong đợi. Kiểm tra câu trả lời này: Sự khác biệt giữa văn bản và varchar
Tôi luôn sử dụng varchar(254)
làm địa chỉ email có thể không dài hơn 254 ký tự.
Xem https://stackoverflow.com/questions/386294/what-is-the-maximum-length-of-a-valid-email-address
Postgresql không có loại tích hợp cho địa chỉ email, mặc dù tôi đã bắt gặp một số loại dữ liệu đóng góp.
Ngoài ra, bạn có thể muốn thêm một trình kích hoạt hoặc một số logic như vậy để chuẩn hóa địa chỉ email trong trường hợp bạn muốn thêm một khóa duy nhất vào nó.
Cụ thể, domain
một phần của địa chỉ email (có dạng local-part
@ domain
không phân biệt chữ hoa chữ thường trong khi local-part
phải được coi là phân biệt chữ hoa chữ thường . Xem http://tools.ietf.org/html/rfc5321#section-2.4
Một cân nhắc khác là nếu bạn muốn lưu trữ tên và địa chỉ email trong biểu mẫu "Joe Bloggs" <joe.bloggs@hotmail.com>
, trong trường hợp đó bạn cần một chuỗi dài hơn 254 ký tự và bạn sẽ không thể sử dụng một ràng buộc duy nhất. Tôi sẽ không làm điều này và đề nghị lưu trữ tên và địa chỉ email riêng biệt. Địa chỉ in đẹp ở định dạng này luôn có thể có trong lớp trình bày của bạn.
@
).
@
) = 320. Có lẽ tôi đang hiểu sai về nó.
Bạn có thể quan tâm đến việc sử dụng kiểm tra CONSTRAINT (có thể dễ dàng hơn, nhưng có thể từ chối nhiều hơn bạn muốn hoặc bạn sử dụng CHỨC NĂNG, thảo luận ở đây và ở đây . Về cơ bản, đó là tất cả về sự đánh đổi giữa tính cụ thể và dễ thực hiện. Mặc dù, PostgreSQL thậm chí có một loại địa chỉ IP gốc, nhưng có một dự án trên pgfoundry cho một loại dữ liệu email ở đây . Tuy nhiên, điều tốt nhất tôi tìm thấy về đây là một tên miền email. Tên miền tốt hơn ràng buộc kiểm tra bởi vì nếu bạn thay đổi nó, bạn chỉ phải thực hiện một lần trong định nghĩa miền và không theo dõi các bảng cha-con thay đổi tất cả các ràng buộc kiểm tra của bạn. Tên miền thực sự tuyệt vời - giống như kiểu dữ liệu, nhưng đơn giản hơn để thực hiện. Tôi đã sử dụng chúng trong Firebird - Oracle thậm chí không có chúng!