sql >> データベース >  >> RDS >> PostgreSQL

Postgresの制約

    PostgreSQLは非常に拡張性があるため、これは「簡単」です。独自の型、型の比較演算子、およびbtreeで使用する演算子クラスを定義できます。 PostgreSQLがそれらを比較する方法を認識できるようにインデックスを付けます。

    秘訣は、競合する値が等しくなるように「等しい」を定義することです。

    まず、タイプを定義します:

    CREATE TYPE tod AS ENUM ('morning', 'afternoon', 'anytime');
    

    次に、インデックスサポートルーチンを定義します。 btree インデックスは値を比較する方法を知っています:

    CREATE FUNCTION tod_compare(tod, tod) RETURNS integer
       IMMUTABLE LANGUAGE sql AS
    $$SELECT CASE WHEN $1 = 'morning' AND $2 = 'afternoon' THEN -1
                WHEN $1 = 'afternoon' AND $2 = 'morning' THEN 1
                ELSE 0
           END$$;
    

    この比較関数に基づいて、比較演算子を実装する関数を定義します。

    CREATE FUNCTION tod_eq(tod, tod) RETURNS boolean IMMUTABLE LANGUAGE sql
       AS 'SELECT tod_compare($1, $2) = 0';
    
    CREATE FUNCTION tod_lt(tod, tod) RETURNS boolean IMMUTABLE LANGUAGE sql
       AS 'SELECT tod_compare($1, $2) = -1';
    
    CREATE FUNCTION tod_le(tod, tod) RETURNS boolean IMMUTABLE LANGUAGE sql
       AS 'SELECT tod_compare($1, $2) <= 0';
    
    CREATE FUNCTION tod_ge(tod, tod) RETURNS boolean IMMUTABLE LANGUAGE sql
       AS 'SELECT tod_compare($1, $2) >= 0';
    
    CREATE FUNCTION tod_gt(tod, tod) RETURNS boolean IMMUTABLE LANGUAGE sql
       AS 'SELECT tod_compare($1, $2) = 1';
    
    CREATE FUNCTION tod_ne(tod, tod) RETURNS boolean IMMUTABLE LANGUAGE sql
       AS 'SELECT tod_compare($1, $2) <> 0';
    

    これで、タイプに演算子を定義できます:

    CREATE OPERATOR ~=~ (
       PROCEDURE = tod_eq,
       LEFTARG = tod,
       RIGHTARG = tod,
       COMMUTATOR = ~=~,
       NEGATOR = ~<>~
    );
    
    CREATE OPERATOR ~<>~ (
       PROCEDURE = tod_ne,
       LEFTARG = tod,
       RIGHTARG = tod,
       COMMUTATOR = ~<>~,
       NEGATOR = ~=~
    );
    
    CREATE OPERATOR ~<=~ (
       PROCEDURE = tod_le,
       LEFTARG = tod,
       RIGHTARG = tod,
       COMMUTATOR = ~>=~,
       NEGATOR = ~>~
    ); 
    
    CREATE OPERATOR ~<~ (
       PROCEDURE = tod_lt,
       LEFTARG = tod,
       RIGHTARG = tod,
       COMMUTATOR = ~>~,
       NEGATOR = ~>=~
    );
    
    CREATE OPERATOR ~>~ (
       PROCEDURE = tod_gt,
       LEFTARG = tod,
       RIGHTARG = tod,
       COMMUTATOR = ~<~,
       NEGATOR = ~<=~
    );
    
    CREATE OPERATOR ~>=~ (
       PROCEDURE = tod_ge,
       LEFTARG = tod,
       RIGHTARG = tod,
       COMMUTATOR = ~<=~,
       NEGATOR = ~<~
    );
    

    あとは、演算子クラスを定義するだけです。 インデックスの定義に使用できます(これにはスーパーユーザー権限が必要です):

    CREATE OPERATOR CLASS tod_ops DEFAULT FOR TYPE tod USING btree AS
       OPERATOR 1 ~<~(tod,tod),
       OPERATOR 2 ~<=~(tod,tod),
       OPERATOR 3 ~=~(tod,tod),
       OPERATOR 4 ~>=~(tod,tod),
       OPERATOR 5 ~>~(tod,tod),
       FUNCTION 1 tod_compare(tod,tod);
    

    これで、新しいデータ型を使用するテーブルを定義できます。

    tod_opsを定義したので タイプtodのデフォルトの演算子クラスとして 、単純な一意制約を作成でき、基になるインデックスは演算子クラスを使用します。

    CREATE TABLE schedule (
       id integer PRIMARY KEY,
       day date NOT NULL,
       time_of_day tod NOT NULL,
       UNIQUE (day, time_of_day)
    );
    

    テストしてみましょう:

    INSERT INTO schedule VALUES (1, '2018-05-01', 'morning');
    
    INSERT INTO schedule VALUES (2, '2018-05-01', 'afternoon');
    
    INSERT INTO schedule VALUES (3, '2018-05-02', 'anytime');
    
    INSERT INTO schedule VALUES (4, '2018-05-02', 'morning');
    ERROR:  duplicate key value violates unique constraint "schedule_day_time_of_day_key"
    DETAIL:  Key (day, time_of_day)=(2018-05-02, morning) already exists.
    

    PostgreSQLはかっこいいではありませんか?




    1. VBAを使用してExcelでSQLスタイルのクエリを使用する

    2. 一般的なOracleデータ収集ストレージ

    3. 一般的なエラー:1005Laravelスキーマビルドと外部キーを使用してテーブルを作成できません

    4. MySQLのデフォルトの順序はWHEREによって異なります