簡體   English   中英

postgresql:約束在 2 個表中具有唯一值

[英]postgresql: constaint to have unique values across 2 tables

我有 2 張桌子:

CREATE TABLE public."user"
(
    id integer NOT NULL DEFAULT nextval('user_id_seq'::regclass),
    username character varying(256) COLLATE pg_catalog."default",
    CONSTRAINT user_pkey PRIMARY KEY (id)
)

CREATE TABLE public.user_tenant
(
    user_id integer NOT NULL,
    tenant_id integer NOT NULL,
    CONSTRAINT user_fk FOREIGN KEY (user_id)
        REFERENCES public."user" (id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE CASCADE
)

我需要有唯一的值(user.username、user_tenant.tenant_id)。 如何聲明這樣的約束?

我會讓用戶名獨一無二,就像另一個表中的租戶一樣。 完成后,您可以在 user_id 和 tenant_id 上放置一個主鍵:

CREATE TABLE public."user"
(
    id integer NOT NULL DEFAULT nextval('user_id_seq'::regclass),
    username character varying(256) COLLATE pg_catalog."default" unique,
    CONSTRAINT user_pkey PRIMARY KEY (id)
);

CREATE TABLE public.user_tenant
(
    user_id integer NOT NULL,
    tenant_id integer NOT NULL,
    CONSTRAINT user_fk FOREIGN KEY (user_id)
        REFERENCES public."user" (id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE CASCADE,
    CONSTRAINT user_tenant_pk PRIMARY KEY (user_id, tenant_id)
);

順便說一句,不要將“用戶”之類的保留名稱用作表名。

您可以創建一個 function ,它可以檢查多個表的唯一性(此處示例: Postgres unique combination constraint across tables )但看起來您可能需要表結構或遵循弗蘭克海肯斯的回答。

編輯:

CREATE TABLE public."user"
(
    id       SERIAL,
    username character varying(256) COLLATE pg_catalog."default",
    PRIMARY KEY (id)
);

CREATE TABLE public.user_tenant
(
    user_id   integer NOT NULL,
    tenant_id integer NOT NULL,
    CONSTRAINT user_fk FOREIGN KEY (user_id)
        REFERENCES public."user" (id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE CASCADE
);


CREATE OR REPLACE FUNCTION public.check_user_tenant(user_id integer, tenant_id integer)
    RETURNS boolean AS
$$
    DECLARE b_result boolean;
BEGIN
    SELECT (COUNT(*) = 0) INTO b_result
    FROM public.user u
             JOIN public.user_tenant ut ON ut.user_id IN (SELECT id
                                                          FROM public.user i_u
                                                          WHERE i_u.username = u.username)
    WHERE u.id = $1 AND ut.tenant_id = $2;
    RETURN b_result;
END
$$ LANGUAGE 'plpgsql';

ALTER TABLE public.user_tenant
ADD CONSTRAINT check_filename CHECK
(public.check_user_tenant(user_id, tenant_id));

-- Testing:
insert into public."user" (username) VALUES ('foo');
insert into public.user_tenant (user_id, tenant_id) VALUES (1,3);

insert into public."user" (username) VALUES ('foo');
-- Violates constraint:
insert into public.user_tenant (user_id, tenant_id) VALUES (2,3);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM