【问题标题】:How do foreign keys work?外键是如何工作的?
【发布时间】:2012-07-19 13:53:56
【问题描述】:

我以前主要使用不支持外键的 MyISAM 表。查看堆栈溢出,我没有找到关于外键实际作用的简洁明了的解释。我最感兴趣的是连接表,你会有这样的架构:

customers
id category_id

products
id category_id 

categories
id

customerproducts
customer_id product_id

如果我在 customerproducts 上有外键,它将确保只有有效的客户和有效的产品才能进入该表,但是如果我尝试将电话类别中的产品添加到指定为仅对复印机?这会导致违反外键约束吗?

【问题讨论】:

标签: database


【解决方案1】:

我最感兴趣的是连接表,您可以在其中拥有这样的架构:

你不会有这样的模式——它不代表你感兴趣的事实。让我们在 SQL 中画出一些表。 (在 PostgreSQL 中测试)首先,客户和产品。

-- Customer names aren't unique.
create table customers (
  cust_id integer primary key,
  cust_name varchar(15) not null
);
insert into customers values (1, 'Foo'), (2, 'Bar');

-- Product names are unique.
create table products (
  prod_id integer primary key,
  prod_name varchar(15) not null unique
);
insert into products values 
(150, 'Product 1'), (151, 'Product 2'), (152, 'Product 3');

产品有不同的类别。

create table categories (
  cat_name varchar(15) primary key
);
insert into categories values ('Cable'), ('Networking'), ('Phones');

每个产品可能出现在几个类别中。

create table product_categories (
  prod_id integer not null references products,
  cat_name varchar(15) not null references categories,
  primary key (prod_id, cat_name)
);

insert into product_categories values 
(150, 'Cable'), (150, 'Networking'), (151, 'Networking'), (152, 'Phones');

客户可能对几类产品感兴趣。

create table customer_category_interests (
  cust_id integer not null references customers,
  cat_name varchar(15) not null references categories,
  primary key (cust_id, cat_name)
);

-- Nobody's interested in phones
insert into customer_category_interests values
(1, 'Cable'), (1, 'Networking'), (2, 'Networking');

如果我在 customerproducts 上有外键,它将确保只有 有效的客户和只有有效的产品才能进入该表,但是什么 关于我是否尝试将电话类别中的产品添加给客户 指定为只对复印机感兴趣?

客户对他们喜欢的类别中的每个产品并不感兴趣。注意重叠的外键约束。

create table product_interests (
  cust_id integer not null,
  prod_id integer not null,
  cat_name varchar(15) not null,
  foreign key (cust_id, cat_name) references customer_category_interests,
  foreign key (prod_id, cat_name) references product_categories,
  primary key (cust_id, prod_id, cat_name)
);

insert into product_interests values
(1, 150, 'Cable'), (2, 150, 'Networking');

下一次插入将失败,因为客户 1 对手机不感兴趣。

insert into product_interests values
(1, 152, 'Phones');
错误:在表“product_interests”上插入或更新违反了外键约束“product_interests_cust_id_fkey” 详细信息:表“customer_category_interests”中不存在键 (cust_id, cat_name)=(1, Phones)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-13
    • 1970-01-01
    • 1970-01-01
    • 2018-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-17
    相关资源
    最近更新 更多