注意:一张表只能有一个主键,这个主键可以包含多个字段
方式1:建表的同时添加约束 格式: 字段名称 字段类型 primary key
方式2:建表的同时在约束区域添加约束
所有的字段声明完成之后,就是约束区域了
格式: primary key(字段1,字段2)
create table pk01(
id int,
username varchar(20),
primary key (id)
);
insert into pk01 values(1,'tom');-- 成功
insert into pk01 values(1,'tom');-- 失败 Duplicate entry '1' for key 'PRIMARY'
insert into pk01 values(null,'tom');-- 失败 Column 'id' cannot be null
create table pk01(
id int primary key,
username varchar(20),
primary key (id)
);-- 错误的 一张表只能有一个主键
方式3:建表之后,通过修改表结构添加约束
create table pk02(
id int,
username varchar(20)
);
alter table pk02 add primary key(字段名1,字段名2..);
alter table pk02 add primary key(id,username);
insert into pk02 values(1,'tom');-- 成功
insert into pk02 values(1,'tomcat');-- 成功
insert into pk02 values(1,'tomcat');-- 失败
删除主键约束:分两种情况
情况1: 这个字段,只有主键约束,分两步来删除主键约束
第一步: alter table 表名 drop primary key; -- 这样只删除了唯一,他还有个非空约束,所以得再删除非空约束
第二步: alter table [表名] modify [列名] varchar(20) null; --修改字段名还为原来的字段 加上null即可
情况2: 这个字段,是一个int类型字段,既有主键约束,又有自增长约束,那么得先删除自增长约束,在删除主键约束
第一步:删除自增长约束,其实就是修改自增长字段名和数据类型还为原来的字段名和类型
alter table 表名 change 字段名 字段名 数据类型; --删除自增长约束
第二步:删除主键约束
alter table 表名 drop primary key;
第三步:删除非空约束
ALTER TABLE test3 MODIFY sid INT NULL; -- 就是修改字段值可以为null
(1).要求:
-----1.被修饰的字段类型支持自增. 一般int
-----2.被修饰的字段必须是一个key 一般是primary key
(2).正确案例
CREATE TABLE test10(
id INT PRIMARY KEY AUTO_INCREMENT, -- 主键自增长约束
NAME VARCHAR(10),
age INT
)
INSERT INTO test10(NAME,age) VALUES('aa',20);
DELETE FROM test10 WHERE id=13;
SELECT * FROM test10;
(3).错误案例
create table ai01(
id varchar(10) auto_increment
);-- 错误 Incorrect column specifier for column 'id'
create table ai01(
id int auto_increment
);-- 错误 Incorrect table definition; there can be only one auto column and it must be defined as a key
特点:被修饰过的字段唯一,对null不起作用
方式1:建表的同时添加约束 格式: 字段名称 字段类型 unique
create table un(
id int unique,
username varchar(20) unique
);
insert into un value(10,'tom');-- 成功
insert into un value(10,'jack');-- 错误 Duplicate entry '10' for key 'id'
insert into un value(null,'jack');-- 成功
insert into un value(null,'rose');-- 成功
方式2:建表的同时在约束区域添加约束
所有的字段声明完成之后,就是约束区域了
unique(字段1,字段值2...)
方式3:建表之后,通过修改表结构添加约束
alter table 表名 add unique(字段1,字段2);-- 添加的联合唯一
alter table 表名 add unique(字段1);-- 给一个添加唯一
alter table 表名 add unique(字段2);-- 给另一个添加唯一
create table un01(
id int,
username varchar(20)
);
alter table un01 add unique(id,username);
insert into un01 values(1,'tom');-- 添加成功
insert into un01 values(1,'jack');-- 添加成功
insert into un01 values(1,'tom');-- 添加失败 Duplicate entry '1-tom' for key 'id'
特点:被修饰过的字段非空
方式:
create table nn(
id int not null,
username varchar(20) not null
);
insert into nn values(null,'tom');-- 错误的 Column 'id' cannot be null
在了解外键约束之前得先了解一下表和表之间的关系及ER图
1.一对多关系的外键约束
-- 创建用户表 (一)
create table user(
id int primary key auto_increment,
username varchar(20)
);
-- 创建订单表 (多)
create table orders(
id int primary key auto_increment,
totalprice double,
user_id int
);
为了保证数据的有效性和完整性,添加约束(外键约束).
在多表的一方添加外键约束★
格式:
alter table 多表名称 add foreign key(外键名称) references 一表名称(主键);
例如:
alter table orders add foreign key(user_id) references user(id);
方式1: 级联删除
ALTER TABLE orders ADD FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE;
然后你就可以删除主表中的数据了
当然你可以级联删除和级联更新 都加上 FOREIGN KEY (sid) REFERENCES stu(sid) ON DELETE CASCADE ON UPDATE CASCADE)
方式2:先把带有外键的多表的数据删除,再删除一表中的数据
2.多对多关系的外键约束
例子:商品和订单
-- 创建商品表
create table product(
id int primary key auto_increment,
name varchar(20),
price double
);
-- 创建中间表
create table orderitem(
oid int,
pid int
);
-- 创建订单表 (多)
create table orders(
id int primary key auto_increment,
totalprice double,
user_id int
);
-- 添加外键约束
alter table orderitem add foreign key(oid) references orders(id);
alter table orderitem add foreign key(pid) references product(id);
特点:值必须是枚举里包含的值
CREATE TABLE test13(
id TINYINT UNSIGNED, -- 非负约束
NAME VARCHAR(10),
sex ENUM('男','女') -- enum 枚举类型
)
INSERT INTO test13 VALUES(255,'aa','你'); --添加失败:‘你’不是枚举里的值
特点:不能添加负数的值,而且可以增加值的范围。例如:int 类型的范围是 (-2的31次方~2的31次方-1),加上非负约束后,值的范围是(0 ~ 2的32次方-1)
CREATE TABLE test12(
id TINYINT UNSIGNED, -- 非负约束
NAME VARCHAR(10),
age INT
)
INSERT INTO test12 VALUES(255,'aa',20);
-- 创建用户表 (一)
create table user(
id int primary key auto_increment,
username varchar(20)
);
-- 创建订单表 (多)
create table orders(
id int primary key auto_increment,
totalprice double,
user_id int
);
1.内连接:
------显式内连接:不符合条件的信息,不做展示
SELECT user.*,orders.`id`,orders.`price`,orders.`user_id` FROM USER,orders WHERE user.id=orders.`user_id`;
SELECT u.id AS 用户编号,u.`username` 用户名,o.`id` AS 订单号,o.`price` 订单价格,o.`user_id` 外键 FROM USER AS u,orders AS o WHERE u.`id`=o.`user_id`;
------隐式内连接 inner join on (inner) 可以省略不写
SELECT user.*,orders.* FROM USER INNER JOIN orders ON user.`id`=orders.`user_id`;
2.外连接
----- 左外连接: LEFT 关键字 左边的表中的信息会全部展示,在右边表中没有符合条件的以NULL展示
!特点:LEFT 左边的表中的信息全部展示,没有对应的以null展示
SELECT user.*,orders.* FROM USER LEFT OUTER JOIN orders ON user.`id`=orders.`user_id`;(OUTER可以省略不写)
----- 右外连接:查询所有订单是属于哪个用户的,所有的订单信息必须展示,这个订单没有对应的用户以NULL展示
!特点:RIGHT 右边的表中的信息全部展示,没有对应的以null展示
SELECT orders.*,user.* FROM USER RIGHT OUTER JOIN orders ON user.`id`=orders.`user_id`;(OUTER可以省略不写)
!!!左外连接和右外连接可以互换
3.子查询
特点:解决 一步查不出来的问题, 一个主查询的查询条件,需要依赖于一个子查询,子查询需要用括号括起来
方式1:采用子查询查询
一.案例演示: 查看用户为张三的订单详情
1. 先在 用户表中查询出张三的id
SELECT user.`id` FROM USER WHERE user.`username`='张三';
2. 拿着张三的id 去订单表中查询 张三的订单信息
SELECT orders.* FROM orders WHERE orders.`user_id`=3;
3.把以上两步合二为一
SELECT orders.* FROM orders WHERE orders.`user_id`=(SELECT user.`id` FROM USER WHERE user.`username`='张三');
二.案例演示: 查询出订单的价格大于300的所有用户信息。
1. 先在订单表里面,查出订单价格大于300的订单编号
SELECT orders.`user_id` FROM orders WHERE orders.`price`>300;
2. 拿着订单号,去用户表里面查
SELECT user.* FROM USER WHERE user.`id`=3 OR user.`id`=5;
3.把以上两步合二为一
SELECT user.* FROM USER WHERE user.id IN(SELECT orders.`user_id` FROM orders WHERE orders.`price`>300);
三.案例演示: 查询订单价格大于300的订单信息及相关用户的信息。
1. 查询订单价格大于300的订单
SELECT orders.* FROM orders WHERE orders.`price`>300;
2. 查询用户信息,并且还有他对应的订单信息
SELECT user.*,lsb.* FROM USER,(SELECT orders.* FROM orders WHERE orders.`price`>300) AS lsb WHERE user.`id`=lsb.user_id;
方式2:采用显式内连接查询
一.案例演示: 查看用户为张三的订单详情
1. 先在 用户表中查询出张三的id
SELECT user.`id` FROM USER WHERE user.`username`='张三';
2. 拿着张三的id 去订单表中查询 张三的订单信息
SELECT orders.* FROM orders WHERE orders.`user_id`=3;
SELECT orders.* FROM orders WHERE orders.`user_id`=(SELECT user.`id` FROM USER WHERE user.`username`='张三');
3. 查看用户为张三的订单详情 要求用户和订单都有展示
SELECT user.*,lsb.* FROM USER,(SELECT orders.* FROM orders WHERE orders.`user_id`=(SELECT user.`id` FROM USER WHERE user.`username`='张三')) AS lsb WHERE user.`id`=lsb.user_id;
-- ★★子查询查出来的一张临时表,再要去跟其他表联合查询,注意这个连接条件,中字段重名的问题,你要用别名区分一下
二.案例演示:查询所有订单所包含的商品信息
SELECT orders.*,orderitem.* FROM orders LEFT OUTER JOIN orderitem ON orders.`id`=orderitem.`oid`;
SELECT orders.*,product.* FROM orders LEFT OUTER JOIN orderitem ON orders.`id`=orderitem.`oid` LEFT OUTER JOIN product ON orderitem.`pid`=product.`id`;
三.案例演示:查询该用户的订单信息,以及订单里面的商品
SELECT user.*,orders.*,product.* FROM USER LEFT OUTER JOIN orders ON user.`id`=orders.`user_id` LEFT JOIN orderitem ON orders.id=orderitem.`oid` LEFT JOIN product ON orderitem.`pid`=product.`id`;
-- 第一步查 用户跟订单 得到一张临时表
-- 第二步 拿着上步的临时表 跟 中间表 去查,又得到一张临时表
-- 再拿着第二步的临时表 跟商品表去查
4.自查询
-- 比如:我要查询emp表中 员工姓名 所对应的 上司姓名
员工 上司
-- smith ford
-- ford jones
-- jones king
-- 把 emp 表 看作两张表 a , b
-- 条件 a 表的上司号=b表的员工号
SELECT a.`mgr` AS 上司号,a.ename,b.ename,b.`empno` 员工号 FROM emp AS a,emp AS b WHERE a.`mgr`=b.`empno`;