一、单表的约束
1.代表记录的唯一标识
2.声明某一列作为主键
·使用关键字primary key
3.主键的特点
·唯一
·非空
·被引用
4.创建一张表,声明主键
(1)第一种
(勾掉自动递增只加了主键,如果新增2个id为19的,就不行了,如果我不给值也不行
数据量庞大我们是记不住哪个是哪个的,我们打上自动递增,再新增就会默认往下加。自动递增保证数据唯一,但是不保证填充空位。)
create table person(
id int primary key,
name varchar(30)
);
insert into person values (1,'聪聪');
insert into person values (2,'美美');
insert into person values (3,'小凤');

Int不指定长度默认值为11
(2)第二种
create table person(
id int,
name varchar(30),
primary key (id)
);
自增长:维护主键信息
auto_increment;
create table person(
id int primary key auto_increment,
name varchar(30)
);
insert into person values (null,'聪聪');
insert into person values (null,'美美');
insert into person values (null,'小凤');
删除id为1的数据
delete from person where id = 1;
唯一和非空的解释
1.唯一:字段唯一,使用关键字unique;
2.非空:不允许为null,使用not null;比如主键
二、多表外键的约束
create table dept(
did int primary key auto_increment,
dname varchar(30)
);
create table emp(
eid int primary key auto_increment,
ename varchar(30),
sal double, dno int
);
insert into dept values (1,'研发部');
insert into dept values (2,'人事部');
insert into emp values (null,'聪聪',15000,1);
insert into emp values (null,'邦邦',5000,1);
insert into emp values (null,'美美',6000,2);
insert into emp values (null,'小凤',8000,2);
insert into emp values (null,'如花',8000,null);

问题:
·直接删掉研发部。Delete from dept where did=1;可以删除


·在现实生活中并不合理,如果你避免问题的发生,两个表之间应该设置关系,删掉部门之前必须把部门下对应的成员删掉

可以看见dno为1的成员依然存在
1.引入外键约束
2.添加外键:
·正常情况下(一个部门有多个员工,一个员工只能属于一个部门)
·设置员工标签的dno字段,作为外键,指向部门表的主键。
·修改员工的表,在员工添加外键。
·alter table emp add foreign key emp (dno) references dept (did);
3.直接添加外键
·创建表的时候直接指定外键
create table emp(
eid int primary key auto_increment, ename varchar(30),
sal double, dno int,
foreign key emp(dno) references dept (did)
);
现在再直接删除部门就不可以了
三、表之间的关系(重要)
1.一对一(一张表解决)
一个人对应一个身份证号码,完全可以建立在一张表里边
2.多对一&一对多(可以用主外键约束)
·一对多:一个部门下有多个员工
·多对一:多个员工可以属于一个部门
练习:用户表&订单表
-- 1. 用户表(一的一方)
CREATE TABLE user (
id INT PRIMARY KEY AUTO_INCREMENT,
-- 主键 username VARCHAR(20) NOT NULL
);
-- 2. 订单表(多的一方,存外键 user_id)
CREATE TABLE `order` (
id INT PRIMARY KEY AUTO_INCREMENT,
order_no VARCHAR(30) NOT NULL,
-- 外键:关联 user 表的
id user_id INT, FOREIGN KEY (user_id) REFERENCES user(id) );
插入测试数据
INSERT INTO user(username) VALUES ('张三'),('李四');
INSERT INTO `order`(order_no, user_id) VALUES
('ORDER_001',1), -- 张三的订单
('ORDER_002',1), -- 张三的订单
('ORDER_003',2); -- 李四的订单
关联查询(重点)
-- 查询所有订单,同时显示对应用户名(多对一查询)
SELECT o.id, o.order_no, u.username FROM `order` o LEFT JOIN user u ON o.user_id = u.id;
-- 查询张三的所有订单(一对多查询)
SELECT o.* FROM `order` o JOIN user u ON o.user_id = u.id WHERE u.username = '张三';
3.多对多(需要产生中间表,这个表只维护关系)
学生和所选科目
一个学生可以选择多个科目
一个科目可以被多个学生选择
实操案例:
创建三张表:
-- 1. 学生表
CREATE TABLE student
( id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL
);
-- 2. 课程表
CREATE TABLE course (
id INT PRIMARY KEY AUTO_INCREMENT,
course_name VARCHAR(30) NOT NULL
);
-- 3. 中间表:学生选课表(核心!多对多必须有)
CREATE TABLE student_course (
student_id INT,
course_id INT,
);
-- 联合主键
PRIMARY KEY (student_id, course_id),
-- 两个外键
FOREIGN KEY (student_id) REFERENCES student(id),
FOREIGN KEY (course_id) REFERENCES course(id) );
插入数据:
-- 学生
INSERT INTO student(name) VALUES ('小明'),('小红');
-- 课程
INSERT INTO course(course_name) VALUES ('MySQL'),('Java'),('Python');
-- 选课关系(中间表)
INSERT INTO student_course(student_id, course_id) VALUES
(1,1), -- 小明选 MySQL
(1,2), -- 小明选 Java
(2,1), -- 小红选 MySQL
(2,3); -- 小红选 Python
四、多表关联查询(重点)
-- 查询每个学生选了哪些课
SELECT
s.name, c.course_name
FROM student s JOIN student_course sc
ON
s.id = sc.student_id JOIN course c
ON
sc.course_id = c.id;

-- 查询 MySQL 这门课被哪些学生选了
SELECT s.name
FROM
student s JOIN student_course sc ON s.id = sc.student_id JOIN course c ON sc.course_id = c.id WHERE c.course_name = 'MySQL';

Java中考虑拆成一对多,站在某一个表考虑
五、多表查询(重要)
先建表:
-- 用户表
CREATE TABLE user ( uid INT PRIMARY KEY, name VARCHAR(20) );
-- 订单表
CREATE TABLE orders ( oid INT PRIMARY KEY, uid INT, gid INT, money INT );
-- 商品表
CREATE TABLE goods ( gid INT PRIMARY KEY, gname VARCHAR(20) );
-- 插入数据
INSERT INTO user VALUES (1, '张三'), (2, '李四'), (3, '王五');
INSERT INTO goods VALUES (101, '手机'), (102, '电脑'), (103, '耳机');
INSERT INTO orders VALUES (1, 1, 101, 5000), (2, 1, 102, 8000), (3, 2, 101, 5000), (4, NULL, 103, 200); -- 没有用户的异常订单
1.笛卡尔积(一般要加约束的)

重复了,可以加入where条件再过滤 where dept.did=emp.dno;
2.内连接查询(inner join)
关键字inner join
不是where 是on了,但是效果差不多;
如果不写inner join就不能用on了,使用where, 像隐晦一点的内连接

--1. 用户表(左表)
CREATE TABLE `user` (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(20) NOT NULL );
-- 2. 订单表(右表)
CREATE TABLE `order` (
id INT PRIMARY KEY AUTO_INCREMENT,
order_no VARCHAR(30) NOT NULL,
user_id INT,
FOREIGN KEY (user_id) REFERENCES `user`(id)
);
3.-- 插入数据
INSERT INTO `user`(username) VALUES ('张三'),('李四'),('王五'),('赵六');
INSERT INTO `order`(order_no, user_id) VALUES ('ORDER_001',1), ('ORDER_002',1), ('ORDER_003',2);
LEFT JOIN:
SELECT 字段 FROM 左表 LEFT JOIN 右表 ON 左表.id = 右表.关联id;

RIGHT JOIN:
SELECT 字段 FROM 左表 RIGHT JOIN 右表 ON 左表.id = 右表.关联id;
SELECT u.id AS 用户id, u.username AS 用户名, o.order_no AS 订单号 FROM `user` u RIGHT JOIN `order` o ON u.id = o.user_id;








