繁体   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