PostgreSQL循环外键到多个表
我有三张桌子 聊天室PostgreSQL循环外键到多个表,sql,postgresql,foreign-keys,Sql,Postgresql,Foreign Keys,我有三张桌子 聊天室 创建桌面聊天室 ( id uuid默认uuid_generate_v4()不为空 约束聊天室 主键 约束fk\u聊天室\u群组\u聊天室 参考组聊天室 关于更新级联关于删除级联 限制fk___聊天室____私人聊天室 参考私人聊天室 更新级联时删除级联时, 名称varchar(255)不为空, 描述varchar(255), 剖面图_pic varchar(128), 使用时区默认值now()在时间戳处创建的_不为空, 在带有时区的时间戳处更新了_ ); 群组聊天室 cr
创建桌面聊天室
(
id uuid默认uuid_generate_v4()不为空
约束聊天室
主键
约束fk\u聊天室\u群组\u聊天室
参考组聊天室
关于更新级联关于删除级联
限制fk___聊天室____私人聊天室
参考私人聊天室
更新级联时删除级联时,
名称varchar(255)不为空,
描述varchar(255),
剖面图_pic varchar(128),
使用时区默认值now()在时间戳处创建的_不为空,
在带有时区的时间戳处更新了_
);
群组聊天室
create table group\u chat\u room
(
id uuid不为空
约束组\u聊天室\u pk
主键
约束fk\uuuu组\u聊天室\uuuuu聊天室
参考聊天室
更新级联时删除级联时,
pus_代码字符(7)不为空
约束fk\uuuu组\uu聊天室\uuuu puskesmas
参考文献puskesmas
关于更新级联关于删除级联
);
创建唯一索引组\u聊天室\u pus\u代码\u uindex
在群组聊天室(密码);
私人聊天室
create table private\u聊天室
(
id uuid不为空
约束私密\u聊天室\u pk
主键
约束fk\uuuu私人聊天室\uuuu聊天室
参考聊天室
关于更新级联关于删除级联
);
如您所见,聊天室
具有外键约束,这些外键约束指的是群组聊天室
和私人聊天室
。另外,group\u chat\u room
和private\u chat\u room
都具有引用chat\u room
的FK约束
当我想在聊天室中插入一行时,我会使用这个
聊天室为(
在聊天室(id,名称)中插入值('Some id','Some name')
)
在群组聊天室(id、pus代码)中插入值(“某些id”、“某些代码”);
但是,由于这些限制,这将产生错误
[23503]错误:表“chat_room”上的插入或更新违反外键约束“fk_chat_room_private_chat_room”详细信息:键(id)=(cef8c655-d46a-4f63-bdc8-77113b1b74b4)不在表“private_chat_room”中。
如何只插入到群组聊天室
,而不必将其插入到私人聊天室
?这里的主要问题是创建多个所需的双向外键。你最终可能会解决这个问题。但这使得数据模型更加复杂,代码也更加复杂。而且它是完全没有必要的。只要一张桌子,你就可以完成所有的事情。如果单独需要组聊天室和私人聊天室,则为每个组创建一个视图。此外,作为简单视图,它们是完全可更新的
您可以通过将列“pus_code”移动到聊天室,并添加2个布尔值来指示这是私人聊天室还是团体聊天室,或者两者都是。是的,听起来很奇怪,但你可以得到一个私人的群组聊天室。(注意:在您的设计中没有任何东西阻止它,您得到的错误是因为它是必需的)。如果确实需要,则创建一个检查约束,要求至少有一个布尔列为false
create table chat_room
(
id integer generated always as identity
constraint chat_room_pk
primary key,
name varchar(255) not null,
description varchar(255),
profile_pic varchar(128),
is_private boolean not null default false,
is_group boolean not null default false,
pus_code varchar(7)
constraint fk__group_chat_room__puskesmas
references puskesmas
on update cascade on delete cascade,
created_at timestamp with time zone default now() not null,
updated_at timestamp with time zone,
constraint not_group_of_pus_code_check
check ( (not is_group and pus_code is null)
or (is_group and pus_code is not null)
)
);
-- create unique partial index
create unique index group_chat_room_pus_code_uindex on chat_room(pus_code)
where is_group;
-- group_chat_room
create view group_chat_room
( id
, name
, description
, profile_pic
, is_private
, pus_code
, created_at
, updated_at
) as
select id
, name
, description
, profile_pic
, is_private
, pus_code
, created_at
, updated_at
from chat_room
where is_group;
-- private_chat_room
create view private_chat_room
( id
, name
, description
, profile_pic
, is_group
, pus_code
, created_at
, updated_at
) as
select id
, name
, description
, profile_pic
, is_group
, pus_code
, created_at
, updated_at
from chat_room
where is_private;
有关完整示例和一些测试,请参见。注意:fiddle在generate_uuid_v4()上有一个问题(不存在),所以对于demo我改为identity。它在操作环境中会很好。这里的主要问题是创建多个所需的双向外键。你最终可能会解决这个问题。但这使得数据模型更加复杂,代码也更加复杂。而且它是完全没有必要的。只要一张桌子,你就可以完成所有的事情。如果单独需要组聊天室和私人聊天室,则为每个组创建一个视图。此外,作为简单视图,它们是完全可更新的
您可以通过将列“pus_code”移动到聊天室,并添加2个布尔值来指示这是私人聊天室还是团体聊天室,或者两者都是。是的,听起来很奇怪,但你可以得到一个私人的群组聊天室。(注意:在您的设计中没有任何东西阻止它,您得到的错误是因为它是必需的)。如果确实需要,则创建一个检查约束,要求至少有一个布尔列为false
create table chat_room
(
id integer generated always as identity
constraint chat_room_pk
primary key,
name varchar(255) not null,
description varchar(255),
profile_pic varchar(128),
is_private boolean not null default false,
is_group boolean not null default false,
pus_code varchar(7)
constraint fk__group_chat_room__puskesmas
references puskesmas
on update cascade on delete cascade,
created_at timestamp with time zone default now() not null,
updated_at timestamp with time zone,
constraint not_group_of_pus_code_check
check ( (not is_group and pus_code is null)
or (is_group and pus_code is not null)
)
);
-- create unique partial index
create unique index group_chat_room_pus_code_uindex on chat_room(pus_code)
where is_group;
-- group_chat_room
create view group_chat_room
( id
, name
, description
, profile_pic
, is_private
, pus_code
, created_at
, updated_at
) as
select id
, name
, description
, profile_pic
, is_private
, pus_code
, created_at
, updated_at
from chat_room
where is_group;
-- private_chat_room
create view private_chat_room
( id
, name
, description
, profile_pic
, is_group
, pus_code
, created_at
, updated_at
) as
select id
, name
, description
, profile_pic
, is_group
, pus_code
, created_at
, updated_at
from chat_room
where is_private;
有关完整示例和一些测试,请参见。注意:fiddle在generate_uuid_v4()上有一个问题(不存在),所以对于demo我改为identity。在操作环境下,它可以正常工作。根据私人聊天根目录删除FK约束。真的不应该有一个双向的FK。如果出于某些奇怪的原因需要双向FK(此处不明显),请参阅。并非所有数据库都支持这些代码。此代码在PostgreSQL中无法正常工作。您需要先创建表,然后添加外键约束。另外,确保外键约束标记为可延迟初始延迟
,以便在这些对称表中插入。根据私人聊天根删除FK约束。真的不应该有一个双向的FK。如果出于某些奇怪的原因需要双向FK(此处不明显),请参阅。并非所有数据库都支持这些代码。此代码在PostgreSQL中无法正常工作。您需要先创建表,然后添加外键约束。另外,确保外键约束标记为可延迟初始延迟
,以便在这些对称表中插入。