外部キー制約はインデックスを参照できません。それはテーブルでなければなりません。
外部キー制約は式を参照できません。参照されるテーブルの列名を指している必要があります。
また、参照される列のセットには、一意のインデックス(主キーも暗黙的に修飾されます)が存在する必要があります。
ここで外部キーに関するマニュアルを読むことから始めます。
優れた設計は、カラムを落とすだけb.a_year
です。a.created_at
これは100%冗長であり、いつでも派生させることができます。
列が積極的に必要な場合(たとえば、テーブルの特定の基準に対して1年に1行を強制する場合b
)、次のような目標を達成できます。
CREATE TABLE a (
a_id serial
,created_at timestamp NOT NULL DEFAULT now()
,a_year NOT NULL DEFAULT extract(year FROM now())::int -- redundant, for fk
,CHECK (a_year = extract(year FROM created_at)::int)
);
CREATE UNIQUE INDEX a_id_a_year_idx ON TABLE a (a_id, a_year); -- needed for fk
CREATE TABLE b (
b_id serial
,a_id integer NOT NULL
,a_year int -- doesn't have to be NOT NULL, but might
,CONSTRAINT id_year FOREIGN KEY (a_id, a_year) REFERENCES a(a_id, a_year)
);
@Catcallのコメントの後に更新:列と句CHECK
の組み合わせによる制約は、レジームを強制します。DEFAULT
NOT NULL
または(単純ではありませんが、値を許可します) 、トリガーNULL
を使用して値を維持できます。a.a_year
CREATE OR REPLACE FUNCTION trg_a_insupbef()
RETURNS trigger AS
$BODY$
BEGIN
NEW.a_year := extract(year FROM NEW.created_at)::int;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
CREATE TRIGGER insupbef
BEFORE INSERT OR UPDATE ON a
FOR EACH ROW EXECUTE PROCEDURE trg_a_insupbef();