不同的用户类型/对象在同一个表中拥有内容 - 如何?

Posted

技术标签:

【中文标题】不同的用户类型/对象在同一个表中拥有内容 - 如何?【英文标题】:Different user types / objects own content in same table - how? 【发布时间】:2011-06-09 00:09:25 【问题描述】:

知道如何将不同的对象联系在一起吗?我试图实现的用例是评论通常由用户拥有。所以我有一个 user_id 。但我也有公司页面,公司在其页面上拥有内容,因此所有者是 company_id。 (这当然是由多个用户管理的)

一种方法是拥有 2 个表 user_cmets 和 company_cmets 但问题是我需要每个对象 2 个表,如果我添加更多用户类型,那么我需要多个表。我想要实现的是 1 张桌子:

comment_id PK  
owner_id (user id or company id or etc...)  - fk?

假设我创建了一个所有者表,只是为了将所有用户类型链接在一起,这些列将是什么来获取这些,或者还有其他方式吗?

【问题讨论】:

【参考方案1】:

人员和组织是超类型/子类型关系中事物的一个很好的例子。它们并不相同,但也不是完全不同的。他们有许多共同的属性。个人和组织都有地址和电话号码,个人和组织都可以是诉讼中的原告和被告,个人和组织显然都可以在您的系统中拥有 cmets。

要在 SQL dbms 中实现这一点,请将人和组织共有的列放在一个名为“Parties”的表中。人们独有的列放在人员表中;组织特有的列进入组织表。使用每个子类型一个视图来隐藏实现细节;您的客户使用视图,而不是表格。

您将使用超类型表“Parties”中的密钥作为 cmets 的所有者。 (我认为。)

这是一个简化的示例。

create table parties (
    party_id integer not null unique,
    party_type char(1) not null check (party_type in ('I', 'O')),
    party_name varchar(10) not null unique,
    primary key (party_id, party_type)
);

insert into parties values (1,'I', 'Mike');
insert into parties values (2,'I', 'Sherry');
insert into parties values (3,'O', 'Vandelay');

-- For "persons", a Subtype of "parties"
create table pers (
    party_id integer not null unique,
    party_type char(1) not null default 'I' check (party_type = 'I'),
    height_inches integer not null check (height_inches between 24 and 108),
    primary key (party_id),
    foreign key (party_id, party_type) references parties (party_id, party_type)
);

insert into pers values (1, 'I', 72);
insert into pers values (2, 'I', 60);

-- For "organizations", a subtype of "parties"
create table org (
    party_id integer not null unique,
    party_type CHAR(1) not null default 'O' check (party_type = 'O'),
    ein CHAR(10), -- In US, federal Employer Identification Number
    primary key (party_id),
    foreign key (party_id, party_type) references parties (party_id, party_type)
);

insert into org values (3, 'O', '00-0000000');

create view people as
select t1.party_id, t1.party_name, t2.height_inches
from parties t1
inner join pers t2 on (t1.party_id = t2.party_id);

create view organizations as 
select t1.party_id, t1.party_name, t2.ein
from parties t1
inner join org t2 on (t1.party_id = t2.party_id);

使用您的 dbms 提供的任何功能使视图可更新。 (可能会触发。)然后应用程序代码可以插入到适当的视图中。

【讨论】:

+1 我喜欢通过在persorgs 中使用冗余的“固定值”party_type 列,您可以强制执行 FK 完整性(而不是仅保持 parties.@987654326 @ 作为主要的,这将允许在 persorgs 中重复 party_ids - 因为在没有 party_type 的情况下仍然允许在数据定义中使用)。问题是,parties 表仍然允许 (4, 'I', 'x') 和 (4, 'O', 'y') 存在,因此 party_type 的冗余仍然是必要的。所以查询需要包含party_type。但是,如果 PK 只是 id 并且约束是 uniq(id,type) 那么 OK "问题是,party 表仍然允许 (4, 'I', 'x') 和 (4, 'O', 'y')": 否它没有。试试吧。 (party.party_id 有一个唯一的约束。)需要“party_type”列来克服 SQL 中的缺陷。关系模型不需要它,支持CREATE ASSERTION 的SQL dbms 也不需要它。但是没有支持断言的 SQL dbms。 (party.party_id 有一个独特的限制。)” - 是的,抱歉,错过了。所以查询不需要party_type 并且结构按预期工作+1

以上是关于不同的用户类型/对象在同一个表中拥有内容 - 如何?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Entity Framework Core 在不同的表中多次添加对象 [跟踪错误]

Python 可以将不同的数据类型存储在列表或链表中

Java应该拥有对象地址类型

指向共享对象的指针在拥有它的不同对象中是不同的

如何在单个查询中从两个表中删除数据

如何建立允许不同类型用户在 SqlAlchemy 中注册的数据库关系