约束
完整性约束
- 为防止不规范数据进入数据库中,在用户对数据进行插入,修改,删除操作时,MySQL提供了一种机制来检查数据库中的数据是否满足规定的条件
约束条件 | 约束描述 |
---|---|
PRIMARY KEY | 主键约束 |
NOT NULL | 非空约束,字段不能为空 |
UNIQUE | 唯一约束,字段值唯一 |
CHECK | 检查约束,检查取值范围 |
DEFAULT | 默认值约束,提供默认值 |
AUTO_INCREMENT | 自动增加约束,约束字段的值自动递增 |
FOREIGN KEY | 外键约束,约束表与表之间关系 |
- 列级约束
cmd
CREATE TABLE t_student(
sno INT(4) PRIMARY KEY AUTO_INCREMENT,
sname VARCHAR(5) NOT NULL,
sex CHAR(1) DEFAULT '男' CHECK(sex="男" || sex="女"),
eamil VARCHAR(15) UNIQUE
);
- 表级约束
cmd
CREATE TABLE t_student(
sno INT(4),
sname VARCHAR(5),
sex CHAR(1),
eamil VARCHAR(15),
CONSTRAINT pk_stu PRIMARY KEY (sno),
CONSTRAINT ck_stu_sex CHECK (sex='男'||sex='女'),
);
外键约束
- 外键约束是用来实现数据库表的参照完整性的,可以使两张表紧密结合起来,特别是针对修改或者删除的级联操作时,会保证数据的完整性
- 外键是指表中某个字段的值依赖于另一张表中某个字段值,而被依赖的值必须具有主键约束或者唯一约束。被依赖的表称为父表或者主表,设置外键约束的表称为子表或者从表
cmd
-- 创建主表
CREATE TABLE t_class(
cno INT(4) PRIMARY KEY auto_increment,
cname VARCHAR(10) NOT NULL,
room CHAR(4)
);
cmd
-- 创建子表
CREATE TABLE t_student(
cno INT(4) PRIMARY KEY auto_increment,
sname VARCHAR(5) NOT NULL,
classno int(4)
)
cmd
-- 设置外键约束 可以在创建表约束也可以后面添加
CREATE TABLE t_student(
cno INT(4) PRIMARY KEY auto_increment,
sname VARCHAR(5) NOT NULL,
classno int(4),
CONSTRAINT fk_stu_classno FOREIGN KEY (classno) REFERENCES t_class (cno)
)
ALTER TABLE t_student ADD CONSTRAINT fk_stu_classno FOREIGN KEY (classno) REFERENCES t_class (cno)
外键策略
- no action 不允许操作
cmd
-- 先将对应键改为null
UPDATE t_student set classno = NULL WHERE classno = 2
-- 再删除从表
DELETE FROM t_class WHERE cno =2
- cascade级联操作,操作主表影响从表的外键信息
cmd
-- 删除已有的约束
ALTER TABLE t_student DROP FOREIGN KEY fk_stu_classno;
-- 添加新的,再删除或者更改时将已有的置为null
ALTER TABLE t_student ADD CONSISTENT fk_stu_classno FOREIGN KEY (classno) REFERENCES t_class (cno) on UPDATE CASCADE ON DELETE CASCADE
- set null置空操作
cmd
-- 删除已有的约束
ALTER TABLE t_student DROP FOREIGN KEY fk_stu_classno;
-- 置新添加外键约束
ALTER TABLE t_student ADD CONSTRAINT fk_stu_classno FOREIGN KEY (classno) REFERENCES t_class (cno) ON UPDATE CASCADE ON DELETE CASCADE;
函数
MySQL中提供了大量的函数来简化用户对数据库的操作,比如字符串处理,日期的运算,数值的运算
单行函数
- 单行函数是指对每一条记录输入值进行运算,并得到相应的计算结果,然后返回给用户,也就是说,每条记录作为参数传递,计算得到每条记录返回值
cmd
SELECT empno,ename,LOWER(ename),UPPER(iob) FROM emp;
-- 转换大小写
- 常用单行函数主要包括字段串函数,数值函数,日期与时间函数,流程函数以及其他函数
多行函数
cmd
SELECT MAX(empno),MIN(empno),COUNT(empno),SUM(empno),AVG(empno) FROM emp;
-- 计算出总共的数据结果
多表查询
- 需要对多张表进行查询,而这多张表需要使用外键和主键关联在一起,然后使用连接查询来查询多-张表中满足的要求
- 连接查询类型 cross natural using on
cmd
-- 交叉连接
SELECT * FROM emp CROSS JOIN dept;
-- 缺点没有指定字段所属表,效率低
-- 指定来自哪个表
SELECT e.DEPTNO,e.IOB,d.LOC
FROM emp e
NATURAL JOIN dept d;
-- 自然连接 natural join 缺点:自动匹配表中所有同名列
-- 解决:USING
SELECT *
FROM emp e
INNER JOIN dept d
USING(DEPTNO)
-- using缺点,关联的字段必须是同名的
-- 解决 内连接 ON
SELECT *
FROM emp e
INNER JOIN dept d
ON (e.deptno = d.deptno)
-- 内连接缺点:只显示匹配信息
-- 外连接:可以显示不匹配信息
-- 左外连接 左边全展示
SELECT *
FROM emp e
LEFT OUTER JOIN dept d
ON e.deptno = d.deptno
-- 右外连接 右边全展示
SELECT *
FROM emp e
RIGHT OUTER JOIN dept d
ON e.deptno = d.deptno
-- 全外连接 全部展示,MySQL 不支持
SELECT *
FROM emp e
FULL OUTER JOIN dept d
ON e.deptno = d.deptno
-- 解决全外连接
SELECT *
FROM emp e
LEFT OUTER JOIN dept d
ON e.deptno = d.deptno
UNION
SELECT *
FROM emp e
RIGHT OUTER JOIN dept d
ON e.deptno = d.deptno
SELECT *
FROM emp e
RIGHT OUTER JOIN dept d
ON e.deptno = d.deptno
INNER JOIN salgrade s
ON e.sal BETWEEN s.losal AND s.hisal;
子查询
单行子查询
- 执行多条select语句
cmd
-- 先执行括号里的,在执行外面的
SELECT * FROM emp WHERE sal > (SELECT sal FROM emp WHERE eanme = 'jack')
多行子查询
cmd
-- 查询deptno = 20里的job 在deptno =10里面有的数据
SELECT * FROM emp
WHERE deptno = 20
AND job in (SELECT job FROM emp WHERE deptno =10)
-- 查询任意一个都小
SELECT *
FROM emp
WHERE sal < ANY(SELECT sal FROM emp WHERE job = 'clerk')
AND job != 'clerk';
事务
事务是用来维护数据库完整性的,它能够保证一系列MySQL操作要么全执行,要么全不执行
cmd
CREATE TABLE account(
id INT PRIMARY KEY auto_increment,
uname VARCHAR(10) NOT NULL,
balance DOUBLE
)
SELECT * FROM account;
INSERT INTO account VALUES (null,'小明',2000),(NULL,'丽丽',3000);
-- 丽丽向小明转200
UPDATE account SET balance = balance - 200 WHERE id = 1;
UPDATE account SET balance = balance + 200 WHERE id = 2;
-- 手动开启事务
START TRANSACTION;
UPDATE account SET balance = balance - 200 WHERE id = 1;
UPDATE account SET balance = balance + 200 WHERE id = 2;
-- 手动回滚 刚才操作回滚
ROLLBACK;
-- 手动提交
COMMIT;
脏读
当一个事务正在访问数据并且对数据进行了修改,而这种修改还没提交到数据库中,这时另一个事务也访问了这个数据,因为这个数据还没提交,另一个事务访问到的是脏数据,依据脏数据做的操作时不正确的
不可重复读
指在一个事务内多次读同一数据,在这个事务还没结束时,另一个事务也访问了数据,在第一个事务多次读数据之间,第二个的修改导致第一个事务两次读取不一样,因此称为不可重复读
幻读
幻读与不可重复读类似,它发生在一个事务读取了几行数据,另一个事务插入一些数据时。在随后的查询中,第一个事务就会发现多了一些原本不存在的记录
事务隔离
解决脏读,不可重复读,幻读问题
隔离级别 | 脏读 | 不可重读读 | 幻读 |
---|---|---|---|
READ UNCOMMITTED | √ | √ | √ |
READ COMMITTED | × | √ | √ |
REPEATABLE READ | × | × | √ |
SERIALIZABLE | × | × | × |
cmd
-- 查看默认事务隔离级别
SELECT @@transaction_isolation;
-- 设置隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
视图
将多个表整合到一个视图中,这样只用关注数据结构而不用关注表之间联系
cmd
-- 创建视图 可以修改表中数据
CREATE VIEW myView01
AS
SELECT * FROM emp WHERE deptno =20;
-- 查看视图
SELECT * FROM myView01;
-- 创建/替换多表视图 不能修改表中数据
CREATE OR REPLACE VIEW myView02
AS
SELECT * FROM emp JOIN dept on emp.DEPTNO = dept.DEPTNO
WHERE sal > 2000
存储过程
将存储语句封装起来,需要时调用
cmd
CREATE PROCEDURE myPro1(name VARCHAR(10))
BEGIN
if name IS NULL OR name = '' THEN
SELECT * FROM emp;
ELSE
SELECT * FROM emp WHERE ename LIKE CONCAT('%',name,'%');
END IF;
END;
-- 删除存储过程
DROP PROCEDURE myPro1;
-- 调用存储过程
CALL myPro1('R')
-- FOUND_ROWS() 内置函数,返回查询的条数
CREATE PROCEDURE myPro1(in name VARCHAR(10),out num INT(3))
BEGIN
if name IS NULL OR name = '' THEN
SELECT * FROM emp;
ELSE
SELECT * FROM emp WHERE ename LIKE CONCAT('%',name,'%');
END IF;
SELECT FOUND_ROWS() INTO num;
END;