博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PostgreSQL foreign key
阅读量:6390 次
发布时间:2019-06-23

本文共 3184 字,大约阅读时间需要 10 分钟。

什么是外键?

外键就是用来关联表的节点,是为了保持表的参照完整性。一个表中的外键必须能够在另外一个关系表中能够匹配到.

以中的例子为例:

假如现在有一个订单表,需要确保订单order里面的商品在product里面存在,这里我们就需要在order增加一个外键这个外键就是product表里面的主键

create table product(	product_no  serial constraint product_pkey primary key  ,	name text,	others character varying(100));

上面这个例子创建了一个product表,主键是product_no 主键的名字是product_pkey

 下面创建一个orders表,外键是product_no,参照product表中的product_no

create table orders(    order_no serial primary key,    product_no integer references product (product_no) ,    name text,    others character varying(100));

当创建之后,如果你在order表里面插入一条数据,而所插入的product_no的在product表里面没没有就会出现报错

ERROR:  insert or update on table "orders" violates foreign key constraint "orders_product_no_fkey"DETAIL:  Key (product_no)=(1) is not present in table "product".

回到这里

create table orders(	order_no serial primary key,	product_no integer ,	name integer references product,	others character varying(100));

当我们执行上面一句的时候也是可以通过的,即使外键约束的字段和被引用表的字段不同,只要与参照表主键的数据类型一样就可以了。但是这里并不是很推荐,不方便以后的维护。

在上面这个例子里面提到了一种不同的写法:

create table orders(    order_no serial primary key,    product_no integer  references product,    name text ,    others character varying(100));

上面这种写法,当缺少字段列表的时候,系统会自动引用被引用表的主键作为order表的外键

但是它不能像创建主键一样写成下面这种方式:

create table orders(    order_no serial primary key,    product_no integer foreign key,    name integer,    others character varying(100));

这样会报错

外键也能够像检查约束一样,把一个字段组创建为一个外键,例如:

create table t1(    a integer primary key,    b integer,    c integer,    FOREIGN KEY (b, c)  REFERENCES t2(b,c));

不过执行上面这条SQL之前你需要先执行下面这条,不然没有引用表,说t2不存在:

create table t2(	a integer primary key,	b integer,	c integer,	unique (b,c));

执行完上面这条语句之后就会创建一个组外键。说到这儿可以发现外键不一定是被引用表中的主键,只要外键的字段在被引用表的字段拥有唯一约束就可以。

一个表里面可以创建多个外键,这种实现的原因是为了实现多对多的一种关系,假如你的订单表order有多个商品:

-----------product tablecreate table product(	product_no serial    primary key,	name text);-----------orders tablecreate table orders(	order_no serial primary key,	shipping text);------------relationship tablecreate table order_item(	order_no integer references orders,	product_no integer references product,	detail text,	primary key (product_no,order_no));

最后的关系表order_item:外键和主键是重叠的。在标准里面是允许的。

在生产环境中经常有这样的情况:当创建了某个上面的订单,而在未来的某一刻,商品表中的某个商品被删除了呢?

上面那种情况是不能删除的,你只有把order_item表里面在product有关系的数据删除才能够删除product表中的数据,但是想删除:

-----------product tablecreate table product(	product_no serial    primary key,	name text);-----------orders tablecreate table orders(	order_no serial primary key,	shipping text);------------relationship tablecreate table order_item(	order_no integer references orders on delete restrict,	product_no integer references product on delete cascade,	detail text,	primary key (product_no,order_no));

上面的这段语句,restrict与cascade分别是限制级联

限制的意思是当在关联表里面存在被引用表的值,则不允许删除;

级联的意思是当关联表里面存在被引用表的值,假如删除被引用表的值,那么关联表中的数据也会随之删除

系统默认是restrict

除了上面两个常用的选项之外,为了业务逻辑的考虑有的为了保留数据。还有set null与set default。set default必须保证默认值能够拥有关联性,能够起到外键的效果。不然就会抛出错误,上面的例子中就不可以设置为default,但是你可以设置为null,但是设置为null也会出现问题,就是被引用表的字段数据也是NULL,如果这样就会造成数据混乱的问题。在这里建议在设置关联字段的时候,把它设置为not null。

与ON delete与之对应的还有ON UPDATE。数据更新也是一样的。

对于删除与更新操作,都会扫描关联表的整个表。例如上面的那个例子,当删除product表中的某一条数据的时候,它会扫描整个关联表order_item。所以在这里你需要创建一个索引。以便能够快速扫描。

转载于:https://my.oschina.net/websec/blog/371578

你可能感兴趣的文章
Windows Server中的故障转移群集的实现机制
查看>>
Linux下tomcat内存溢出分析及优化
查看>>
python登陆,注册小程序
查看>>
墨卡托坐标转换成经纬度
查看>>
组策略脚本的趣味应用
查看>>
corosync+pacemaker高可用集群
查看>>
一文总结学习 Python 的 14 张思维导图
查看>>
景安河南机房电力事故,部分主机和云服务器停机
查看>>
1024x600 7" LVDS LCD with Capacitive Touch for pcD
查看>>
解决ubuntu系统安装完后启动项里没有ubuntu的问题
查看>>
JSTL标签
查看>>
我的友情链接
查看>>
Martini 中的 Handler
查看>>
一本跳进挨踢生活圈的日记(南京站)
查看>>
HttpWatch工具简介及使用技巧
查看>>
我的友情链接
查看>>
Objective-C中new与alloc/init的区别
查看>>
手动编译Mysql5.6.10 手动编译php 支持fastcgi
查看>>
MySQL主主
查看>>
linux的权限管理以及特殊权限SUID,SGID,Sticky
查看>>