回答:
DOMAIN
scitext
(大文字と小文字を区別しない)を使用するだけでは十分ではないと思います[1]。PostgreSQLを使用すると、タイプに対して本質的に定義された制約であるカスタムドメインを作成できます。たとえば、タイプ上または上のドメインを作成できます。citext
text
type=email
仕様の使用現在、電子メールアドレスとは何かという質問に対する最も正しい答えは、RFC5322で指定されています。その仕様は非常に複雑であるため[2]、非常に複雑であるため、すべてが壊れています。HTML5には、電子メールの異なる仕様が含まれています。
この要件は、RFC 5322の意図的な違反です。RFC5322では、同時に厳密すぎる( "@"文字の前)、曖昧すぎる( "@"文字の後)、および緩すぎる(コメントを許可する)電子メールアドレスの構文を定義します、空白文字、およびほとんどのユーザーには馴染みのない方法で引用された文字列)がここで実用的になります。[...]次のJavaScriptおよびPerl互換の正規表現は、上記の定義の実装です。
/^[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])?)*$/
これはおそらくあなたが望むものであり、HTML5で十分であれば、おそらく十分です。これをPostgreSQLで直接利用できます。citext
ここでも使用します(技術的には、大文字または小文字のいずれかを削除することで、視覚的に正規表現を少しだけ使用できます)。
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])?)*$' );
できるようになりました...
SELECT 'asdf@foobar.com'::email;
だがしかし
SELECT 'asdf@foob,,ar.com'::email;
SELECT 'asd@f@foobar.com'::email;
それらの両方が戻るため
ERROR: value for domain email violates check constraint "email_check"
これもcitextに基づいているため
SELECT 'asdf@foobar.com'::email = 'ASdf@fooBAR.com';
デフォルトでtrueを返します。
plperlu
/ を使用するEmail::Valid
重要な注意事項として、これを行うより適切な方法がありplperlu
ます。このレベルの正確さが必要な場合は、必要ありませんcitext
。Email::Valid
ドメインにMXレコードがあるかどうかも確認できます(Email :: Validのドキュメントの例)。最初に、plperluを追加します(スーパーユーザーが必要です)。
CREATE EXTENSION plperlu;
次に、関数を作成します。次のようにマークします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';
$$;
その後、ドメインを作成し、
CREATE DOMAIN validemail AS text NOT NULL
CONSTRAINT validemail_check CHECK (valid_email(VALUE));
citext
は技術的に間違っています。SMTPはlocal-part
大文字と小文字を区別すると定義します。しかし、これも仕様が愚かであるというケースです。独自のアイデンティティー危機が含まれています。仕様ではlocal-part
(の前の部分@
)「大文字と小文字を区別する可能性があります」...「大文字と小文字を区別する必要があります」...と「メールボックスローカルパーツの大文字と小文字の区別を悪用すると、相互運用性が妨げられます。」これらの正規表現はいずれも、電子メールアドレス全体、ローカル部分、またはドメイン名の長さ制限を強制しません。RFC 5322は長さの制限を指定していません。これらは、実際に電子メールを送信するためのSMTPプロトコルなどの他のプロトコルの制限に起因します。RFC 1035では、ドメインは63文字以下にする必要があると規定されていますが、構文仕様には含まれていません。理由は、真の通常の言語では長さ制限を強制できず、連続するハイフンを同時に禁止できないからです。
a-z
とA-Z
キャラクタークラスの両方を使用する理由はありますか?
~
は、大文字と小文字が~*
区別されるため、(a)大文字と小文字を区別しないか、(b)文字クラスに大文字と小文字を含める必要があります。
citext
さんは、~
私が求めている理由です、私には大文字と小文字を区別しないと思われます。
CITEXT
メールアドレスは(実際には)大文字と小文字を区別しないため、私は常にメールに使用します。つまり、John @ Example.comはjohn@example.comと同じです。
テキストと比較して、重複を防ぐために一意のインデックスを設定するのも簡単です。
-- 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)));
メールの比較も簡単で、エラーが発生しにくくなります。
SELECT * FROM address WHERE email = 'JOHN@example.com';
と比較して:
SELECT * FROM address WHERE lower(email) = lower('JOHN@example.com');
CITEXT
は、「citext」という名前の標準拡張モジュールで定義されているタイプで、次のように入力することで使用できます。
CREATE EXTENSION citext;
PS text
とvarchar
Postgresで実質的に同じでtext
あり、予想どおりに使用してもペナルティはありません。この回答を確認してください:textとvarcharの違い
varchar(254)
メールアドレスは254文字を超えないように常に使用します。
https://stackoverflow.com/questions/386294/what-is-the-maximum-length-of-a-valid-email-addressを参照してください
Postgresqlには電子メールアドレスの組み込み型はありませんが、寄稿されたデータ型に出くわしました。
さらに、一意のキーを追加する場合に備えて、電子メールアドレスを標準化するトリガーまたはそのようなロジックを追加することもできます。
特に、domain
メールアドレスの一部(local-part
@ 形式domain
は大文字と小文字を区別しlocal-part
ませんが、大文字と小文字を区別する必要があります。http://tools.ietf.org/html/rfc5321#section-2.4を参照してください)
もう1つの考慮事項は、フォーム"Joe Bloggs" <joe.bloggs@hotmail.com>
に名前と電子メールアドレスを保存する場合です。この場合、254文字より長い文字列が必要であり、一意の制約を有意義に使用することはできません。私はこれを行わず、名前とメールアドレスを別々に保存することをお勧めします。プレゼンテーション層では、この形式で住所をきれいに印刷することが常に可能です。
@
)= 320です。おそらく、私はそれを誤って解釈しています。
あなたのチェック使用してに興味があるかもしれない制約をおそらくより簡単に(が、あなたがしたいと思います以上拒否することがあります、またはあなたはFUNCTIONを使用し、議論し、こことここ。Bascially、それは特異性と実装の容易さとのトレードオフについてのすべてだ。興味深いトピック。PostgreSQLはさえネイティブIPアドレスの種類がありますが、電子メールのデータ型のpgFoundryに上のプロジェクトがありますが、ここでは。しかし、私はこのことについて発見された最良の電子メールであるドメイン。ドメインはチェック制約よりも優れています。ドメインを変更する場合、ドメイン定義で一度だけ行う必要があり、親子テーブルをたどってすべてのチェック制約を変更する必要がないためです。ドメインは本当にクールです。データ型に似ていますが、実装が簡単です。Firebirdで使用しました-Oracleにはありません!