[SQL系列] 从头开始学PostgreSQL 约束连接

上一篇的增删改查和基础筛选操作

[SQL系列] 从头开始学PostgreSQL 增删改查_Edward.W的博客-CSDN博客https://blog.csdn.net/u013379032/article/details/131775853这篇大多是基于单张表的一些简单操作,但是我们经常要操作多张表一起查询,有些表的位置还必须要有限制,那怎么办呢?今天还是一起来学习学习。

约束

PostgreSQL的约束是用于规定表中的数据规则,如果违反了这个规则,行为就会被约束终止。

约束是针对表存在的,一般在建表和修改的时候规定,这样可以确保数据库中数据的准确性和可靠性。

一般有这些约束:

1. NOT NULL:用于保证表中某一列的值不为空。

sql 复制代码
CREATE TABLE my_table (  
 id SERIAL PRIMARY KEY,  
 name VARCHAR(255) NOT NULL  
);  

上面的句子使用了NOT NULL约束,插入数据的时候name不能为空。以下是一个反例:

sql 复制代码
INSERT INTO my_table (name, id) VALUES (NULL, 30);  

这个插入语句将被拒绝,因为"name"字段不能为空。

2. UNIQUE:用于保证表中某一列的值唯一。

sql 复制代码
CREATE TABLE my_table (  
 id SERIAL PRIMARY KEY,  
 name VARCHAR(255) UNIQUE NOT NULL  
);  

反例:

sql 复制代码
INSERT INTO my_table(name, id) VALUES ('Alice', 30);  
INSERT INTO my_table (name, id) VALUES ('Alice', 35);  

第二个插入语句将被拒绝,因为"name"字段的值已经存在,不能重复插入。

3. PRIMARY KEY:用于定义表的主键,保证表中每条记录的唯一性。

sql 复制代码
CREATE TABLE my_table (  
 id SERIAL PRIMARY KEY,  
 name VARCHAR(255)   
);  

反例:

sql 复制代码
CREATE TABLE my_table (  
 id SERIAL PRIMARY KEY,  
 name VARCHAR(255)   PRIMARY KEY
);  

这个建表的时候就会出错,因为出现了两个primary key。

4. FOREIGN KEY:用于定义表之间的关系,保证数据的一致性和完整性。

sql 复制代码
CREATE TABLE my_table (  
 id SERIAL PRIMARY KEY,  
 parent_id INTEGER NOT NULL REFERENCES another_table(id)  
);  

反例:在another_table里面插入一条记录

sql 复制代码
INSERT INTO another_table (id) VALUES (1);  

并且插入到my_table表

sql 复制代码
INSERT INTO my_table(parent_id) VALUES (1);  

这时候,如果删除another__table的记录的话:

sql 复制代码
DELETE FROM another_table WHERE id = 1;  

那么"foreign_key_example"表中的记录也将被自动删除。

5. CHECK:用于限制某一列的取值范围。

sql 复制代码
CREATE TABLE my_table (  
 id SERIAL PRIMARY KEY,  
 age INTEGER CHECK (age > 0 AND age < 100)  
);  

反例:

sql 复制代码
INSERT INTO my_table(age) VALUES (-1);  

这个插入语句将被拒绝,因为"age"字段的值不满足 CHECK 约束的条件

6. DEFAULT:用于定义某一列的默认值。

sql 复制代码
ALTER TABLE my_table ALTER COLUMN name SET DEFAULT 'unknown';

反例:

sql 复制代码
insert into my_table(name) value (NULL);

这个插入语句将插入一条记录,其中"name"字段的值为"unknown",因为"name"字段没有提供值,所以使用默认值。

连接

连接就是把两个表或者多个表结合起来,基于表共同的字段进行连接。

总共有以下几种连接:

内部连接(inner join) 全连接(full join) 左连接(left join) 右连接(right join) 交叉连接(cross join)

准备数据:

sql 复制代码
CREATE TABLE classes (  
   id SERIAL PRIMARY KEY,  
   name VARCHAR(50) NOT NULL UNIQUE  
);  

CREATE TABLE students (  
   id SERIAL PRIMARY KEY,  
   name VARCHAR(50) NOT NULL UNIQUE,  
   age INT NOT NULL,  
   gender VARCHAR(10) NOT NULL,  
   class_id INTEGER NOT NULL REFERENCES classes(id)  
);  

INSERT INTO classes (name) VALUES ('班级 1');  
INSERT INTO classes (name) VALUES ('班级 2');  
INSERT INTO classes (name) VALUES ('班级 3');  
INSERT INTO classes (name) VALUES ('班级 4');  
INSERT INTO classes (name) VALUES ('班级 5');  
INSERT INTO classes (name) VALUES ('班级 6');  
INSERT INTO classes (name) VALUES ('班级 7');  
INSERT INTO classes (name) VALUES ('班级 8');  
INSERT INTO classes (name) VALUES ('班级 9');  
INSERT INTO classes (name) VALUES ('班级 10');  


INSERT INTO students (name, age, gender, class_id) VALUES ('张三', 18, '男', 1);  
INSERT INTO students (name, age, gender, class_id) VALUES ('李四', 19, '女', 1);  
INSERT INTO students (name, age, gender, class_id) VALUES ('王五', 20, '男', 2);  
INSERT INTO students (name, age, gender, class_id) VALUES ('赵六', 18, '女', 2);  
INSERT INTO students (name, age, gender, class_id) VALUES ('陈七', 19, '男', 3);  
INSERT INTO students (name, age, gender, class_id) VALUES ('孙八', 20, '女', 3);  
INSERT INTO students (name, age, gender, class_id) VALUES ('周九', 18, '男', 4);  
INSERT INTO students (name, age, gender, class_id) VALUES ('吴十', 19, '女', 4);  
INSERT INTO students (name, age, gender, class_id) VALUES ('郑十一', 20, '男', 5);  
INSERT INTO students (name, age, gender, class_id) VALUES ('王十二', 18, '女', 5);  

cross join (交叉连接)

交叉连接(CROSS JOIN)把第一个表的每一行与第二个表的每一行进行匹配。如果两个输入表分别有 x 和 y 行,则结果表有 x*y 行。

由于交叉连接(CROSS JOIN)有可能产生非常大的表,使用时必须谨慎,只在适当的时候使用它们。

sql 复制代码
testdb=# SELECT * FROM classes CROSS JOIN students S;
 id |  name   | id |  name  | age | gender | class_id
----+---------+----+--------+-----+--------+----------
  1 | 班级 1  |  1 | 张三   |  18 | 男     |        1
  1 | 班级 1  |  2 | 李四   |  19 | 女     |        1
  1 | 班级 1  |  3 | 王五   |  20 | 男     |        2
  1 | 班级 1  |  4 | 赵六   |  18 | 女     |        2
  1 | 班级 1  |  5 | 陈七   |  19 | 男     |        3
  1 | 班级 1  |  6 | 孙八   |  20 | 女     |        3
  1 | 班级 1  |  7 | 周九   |  18 | 男     |        4
  1 | 班级 1  |  8 | 吴十   |  19 | 女     |        4
  1 | 班级 1  |  9 | 郑十一 |  20 | 男     |        5
  1 | 班级 1  | 10 | 王十二 |  18 | 女     |        5
  2 | 班级 2  |  1 | 张三   |  18 | 男     |        1
  2 | 班级 2  |  2 | 李四   |  19 | 女     |        1
  2 | 班级 2  |  3 | 王五   |  20 | 男     |        2
  2 | 班级 2  |  4 | 赵六   |  18 | 女     |        2
  2 | 班级 2  |  5 | 陈七   |  19 | 男     |        3
  2 | 班级 2  |  6 | 孙八   |  20 | 女     |        3
  2 | 班级 2  |  7 | 周九   |  18 | 男     |        4
  2 | 班级 2  |  8 | 吴十   |  19 | 女     |        4
  2 | 班级 2  |  9 | 郑十一 |  20 | 男     |        5
  2 | 班级 2  | 10 | 王十二 |  18 | 女     |        5
  3 | 班级 3  |  1 | 张三   |  18 | 男     |        1
  3 | 班级 3  |  2 | 李四   |  19 | 女     |        1
  3 | 班级 3  |  3 | 王五   |  20 | 男     |        2
  3 | 班级 3  |  4 | 赵六   |  18 | 女     |        2
  3 | 班级 3  |  5 | 陈七   |  19 | 男     |        3
  3 | 班级 3  |  6 | 孙八   |  20 | 女     |        3
  3 | 班级 3  |  7 | 周九   |  18 | 男     |        4
  3 | 班级 3  |  8 | 吴十   |  19 | 女     |        4
  3 | 班级 3  |  9 | 郑十一 |  20 | 男     |        5
  3 | 班级 3  | 10 | 王十二 |  18 | 女     |        5
  4 | 班级 4  |  1 | 张三   |  18 | 男     |        1
  4 | 班级 4  |  2 | 李四   |  19 | 女     |        1
  4 | 班级 4  |  3 | 王五   |  20 | 男     |        2
  4 | 班级 4  |  4 | 赵六   |  18 | 女     |        2
  4 | 班级 4  |  5 | 陈七   |  19 | 男     |        3
  4 | 班级 4  |  6 | 孙八   |  20 | 女     |        3
  4 | 班级 4  |  7 | 周九   |  18 | 男     |        4
  4 | 班级 4  |  8 | 吴十   |  19 | 女     |        4
  4 | 班级 4  |  9 | 郑十一 |  20 | 男     |        5
  4 | 班级 4  | 10 | 王十二 |  18 | 女     |        5
  5 | 班级 5  |  1 | 张三   |  18 | 男     |        1
  5 | 班级 5  |  2 | 李四   |  19 | 女     |        1
  5 | 班级 5  |  3 | 王五   |  20 | 男     |        2
  5 | 班级 5  |  4 | 赵六   |  18 | 女     |        2
  5 | 班级 5  |  5 | 陈七   |  19 | 男     |        3

left join(左连接)

左连接是指将左表中的所有数据与右表中的数据进行匹配,如果右表中没有匹配的数据,则返回左表中的数据以及一个空值。左连接可以使用 left join 语句进行查询。

sql 复制代码
testdb=# SELECT * FROM classes C LEFT JOIN students S ON S.class_id = C.id;
 id |  name   | id |  name  | age | gender | class_id
----+---------+----+--------+-----+--------+----------
  1 | 班级 1  |  1 | 张三   |  18 | 男     |        1
  1 | 班级 1  |  2 | 李四   |  19 | 女     |        1
  2 | 班级 2  |  3 | 王五   |  20 | 男     |        2
  2 | 班级 2  |  4 | 赵六   |  18 | 女     |        2
  3 | 班级 3  |  5 | 陈七   |  19 | 男     |        3
  3 | 班级 3  |  6 | 孙八   |  20 | 女     |        3
  4 | 班级 4  |  7 | 周九   |  18 | 男     |        4
  4 | 班级 4  |  8 | 吴十   |  19 | 女     |        4
  5 | 班级 5  |  9 | 郑十一 |  20 | 男     |        5
  5 | 班级 5  | 10 | 王十二 |  18 | 女     |        5
 10 | 班级 10 |    |        |     |        |
  8 | 班级 8  |    |        |     |        |
  6 | 班级 6  |    |        |     |        |
  9 | 班级 9  |    |        |     |        |
  7 | 班级 7  |    |        |     |        |
(15 rows)

right join(右连接)

右连接是指将右表中的所有数据与左表中的数据进行匹配,如果左表中没有匹配的数据,则返回右表中的数据以及一个空值。右连接可以使用 right join 语句进行查询。

sql 复制代码
testdb=# SELECT * FROM classes C RIGHT JOIN students S ON S.class_id = C.id;
 id |  name  | id |  name  | age | gender | class_id
----+--------+----+--------+-----+--------+----------
  1 | 班级 1 |  1 | 张三   |  18 | 男     |        1
  1 | 班级 1 |  2 | 李四   |  19 | 女     |        1
  2 | 班级 2 |  3 | 王五   |  20 | 男     |        2
  2 | 班级 2 |  4 | 赵六   |  18 | 女     |        2
  3 | 班级 3 |  5 | 陈七   |  19 | 男     |        3
  3 | 班级 3 |  6 | 孙八   |  20 | 女     |        3
  4 | 班级 4 |  7 | 周九   |  18 | 男     |        4
  4 | 班级 4 |  8 | 吴十   |  19 | 女     |        4
  5 | 班级 5 |  9 | 郑十一 |  20 | 男     |        5
  5 | 班级 5 | 10 | 王十二 |  18 | 女     |        5
(10 rows)

inner join(内连接)

内连接是连接的两个表中的数据进行匹配,如果匹配不到数据,则不返回结果。内连接可以使用 select 语句进行查询。

sql 复制代码
testdb=# SELECT * FROM classes C inner JOIN students S ON S.class_id = C.id;
 id |  name  | id |  name  | age | gender | class_id
----+--------+----+--------+-----+--------+----------
  1 | 班级 1 |  1 | 张三   |  18 | 男     |        1
  1 | 班级 1 |  2 | 李四   |  19 | 女     |        1
  2 | 班级 2 |  3 | 王五   |  20 | 男     |        2
  2 | 班级 2 |  4 | 赵六   |  18 | 女     |        2
  3 | 班级 3 |  5 | 陈七   |  19 | 男     |        3
  3 | 班级 3 |  6 | 孙八   |  20 | 女     |        3
  4 | 班级 4 |  7 | 周九   |  18 | 男     |        4
  4 | 班级 4 |  8 | 吴十   |  19 | 女     |        4
  5 | 班级 5 |  9 | 郑十一 |  20 | 男     |        5
  5 | 班级 5 | 10 | 王十二 |  18 | 女     |        5
(10 rows)

full join(全连接)

全连接是指将左表和右表中的所有数据进行匹配,如果左表或右表中没有匹配的数据,则返回空值。全连接可以使用 full outer join 语句进行查询。

sql 复制代码
testdb=# SELECT * FROM classes C FULL JOIN students S ON S.class_id = C.id;
 id |  name   | id |  name  | age | gender | class_id
----+---------+----+--------+-----+--------+----------
  1 | 班级 1  |  1 | 张三   |  18 | 男     |        1
  1 | 班级 1  |  2 | 李四   |  19 | 女     |        1
  2 | 班级 2  |  3 | 王五   |  20 | 男     |        2
  2 | 班级 2  |  4 | 赵六   |  18 | 女     |        2
  3 | 班级 3  |  5 | 陈七   |  19 | 男     |        3
  3 | 班级 3  |  6 | 孙八   |  20 | 女     |        3
  4 | 班级 4  |  7 | 周九   |  18 | 男     |        4
  4 | 班级 4  |  8 | 吴十   |  19 | 女     |        4
  5 | 班级 5  |  9 | 郑十一 |  20 | 男     |        5
  5 | 班级 5  | 10 | 王十二 |  18 | 女     |        5
 10 | 班级 10 |    |        |     |        |
  8 | 班级 8  |    |        |     |        |
  6 | 班级 6  |    |        |     |        |
  9 | 班级 9  |    |        |     |        |
  7 | 班级 7  |    |        |     |        |
(15 rows)
相关推荐
向上的车轮20 分钟前
Django学习笔记二:数据库操作详解
数据库·django
编程老船长31 分钟前
第26章 Java操作Mongodb实现数据持久化
数据库·后端·mongodb
Mephisto.java31 分钟前
【力扣 | SQL题 | 每日四题】力扣2082, 2084, 2072, 2112, 180
sql·算法·leetcode
全栈师1 小时前
SQL Server中关于个性化需求批量删除表的做法
数据库·oracle
Data 3171 小时前
Hive数仓操作(十七)
大数据·数据库·数据仓库·hive·hadoop
BergerLee2 小时前
对不经常变动的数据集合添加Redis缓存
数据库·redis·缓存
gorgor在码农2 小时前
Mysql 索引底层数据结构和算法
数据结构·数据库·mysql
-seventy-2 小时前
SQL语句 (MySQL)
sql·mysql
bug菌¹3 小时前
滚雪球学Oracle[6.2讲]:Data Guard与灾难恢复
数据库·oracle·data·灾难恢复·guard
一般路过糸.3 小时前
MySQL数据库——索引
数据库·mysql