Database 表的外键可以是同一表的复合主键的一部分吗?
假设我有两个表:A(列为A、b、c、d)和b(列为x、y、z)。现在,Database 表的外键可以是同一表的复合主键的一部分吗?,database,database-design,data-modeling,Database,Database Design,Data Modeling,假设我有两个表:A(列为A、b、c、d)和b(列为x、y、z)。现在,(a,b)一起构成表a的主键,x是表b的主键。是否可以将b作为表a的外键,从表b中引用x 请尽快回复 提前感谢!:-) 是的,这没有问题。一个典型的示例(使用MySQL进行演示)是一个数据库表,其中包含多个公司,另一个包含可以为其中任何一个公司工作的员工: create table companies ( id int primary key, name varchar(20))
(a,b)
一起构成表a的主键,x
是表b的主键。是否可以将b
作为表a的外键,从表b中引用x
请尽快回复
提前感谢!:-) 是的,这没有问题。一个典型的示例(使用MySQL进行演示)是一个数据库表,其中包含多个公司,另一个包含可以为其中任何一个公司工作的员工:
create table companies (
id int primary key,
name varchar(20));
create table employees (
id int,
c_id varchar(20) references companies(id),
name varchar(20),
primary key (id, c_id));
insert into companies (id, name) values (1, 'ABC');
insert into companies (id, name) values (2, 'DEF');
insert into companies (id, name) values (3, 'HIJ');
insert into employees (id, c_id, name) values (101, 1, "Allan");
insert into employees (id, c_id, name) values (102, 1, "Bobby");
insert into employees (id, c_id, name) values (101, 2, "Carol");
insert into employees (id, c_id, name) values (101, 3, "David");
请注意,员工
的主键是由员工ID和公司ID组成的复合键。还请注意,公司ID是对公司
主键的外键约束,即您询问的确切情况(功能上)
显示谁为哪家公司工作的查询显示了这一点:
select c.id, c.name, e.id, e.name
from companies c, employees e
where c.id = e.c_id
order by c.id, e.id
c.id c.name e.id e.name
---- ------ ---- ------
1 ABC 101 Allan
1 ABC 102 Bobby
2 DEF 101 Carol
3 HIJ 101 David
复合主键中的列也可以是引用另一个表的主键的外键吗?当然可以。重要的问题是,这什么时候是个好主意 最常见的场景可能是交叉点或连接表。客户可以有多个地址(发货、账单等),并且地址可以有多个客户使用它们。因此,表CUSTOMER\u ADDRESSES有一个主键,该主键同时引用CUSTOMER和ADDRESS主键(对于奖励积分,ADDRESS\u类型也引用数据表) 我的示例使用Oracle 12c语法:
create table customer_address
( customer_id number(38,0) not null
, address_id number(38,0) not null
, address_type_code varchar2(3) not null
, constraint customer_address_pk primary key
(customer_id, address_id, address_type_code)
, constraint customer_address_customer_fk foreign key
(customer_id) references customer(customer_id)
, constraint customer_address_address_fk foreign key
(address_id) references address(address_id)
, constraint customer_address_type_fk foreign key
(address_type_code) references address_type(address_type_code)
);
第二种情况发生在子表的主键由父键和仅在父键内唯一的标识符(通常是数字)组成时。例如,订单有一个订单标题和一些订单行。订单由订单标题ID标识,其行由单调递增的数字标识。订单行表可能如下所示:
create table order_line
( order_header_id number(38,0) not null
, order_line_no number(38,0) not null
, product_id number(38,0) not null
, qty number(38,0) not null
, constraint order_line_pk primary key
(order_header_id, order_line_no)
, constraint order_line_header_fk foreign key
(order_header_id) references order_header(order_header_id)
, constraint order_line_product_fk foreign key
(product_id) references product(product_id)
);
请注意,我们可以将订单行建模为另一个交集表,主键为(订单头id、产品id)
,并将订单行编号
降级为普通属性的状态:这取决于我们必须表示的业务规则
第二种情况比你想象的要少见:复合主键在现实生活中非常罕见。例如,我认为中介绍的模型很弱。我们可能需要将员工用作许多关系(例如经理、任务、销售)的外键。使用复合键作为外键很笨拙(需要更多的输入!)。此外,当我们深入研究这些模型时,我们经常发现其中一个键列是自然键而不是主键,因此可能会发生更改。将更改级联到复合外键中的自然键列是一个PITN
因此,通常使用代理(或合成)主键,例如使用序列或标识列,并使用唯一约束强制自然键。后一步常常被遗忘,但它对于保持引用完整性至关重要。如果我们需要存储来自多家公司的员工的详细信息,包括公司的员工标识符,我们可能会有这样一个员工表:
create table employee
( employee_id number(38,0) generated always as number
, company_id number(38,0) not null
, company_employee_id varchar2(128) not null
, name varchar2(128) not null
, constraint employee_pk primary key
(employee_id)
, constraint employee_uk unique
(company_id, company_employee_id)
, constraint employee_company_fk foreign key
(company_id) references company(company_id)
);
在数据仓库和其他VLDB中,通常会发现级联到依赖表的复合主键。这里,复合键列构成了非规范化策略的一部分,以支持分区方案和/或有效的访问路径。当然可以。你为什么不自己试试呢。写两个
CREATE TABLE
语句所需的时间与写那个问题所需的时间一样长。请不要使用像“尽快”这样的东西——这不是一个付费的支持平台。