目录
约束
约束的概念
1.约束是作用在表中列上的规则,用于限制加入表的数据
2.为了什么??为了保障数据库中数据的真实性、有效性、完整性
比如,一个人的年龄不可能为2000,这个时候就需要约束来保障数据的有效。
约束的分类
注意:MySQL不支持检查约束
约束的演示
创建一个员工表,表内各个列有一定的约束条件:
CREATE TABLE emp(
id int PRIMARY KEY, -- 员工id,主键且自增
name varchar(20) NOT NULL UNIQUE, -- 员工姓名,非空且唯一
joindata date NOT NULL, -- 入职日期,非空
salary double(7,2) NOT NULL, -- 工资,非空
bonus double(7,2) DEFAULT 0 -- 奖金,如果没有默认为0
)
如果有超出约束条件的语句,会报错:
主键是唯一的
auto_increment只能用于非空且唯一的列
外键约束
概念:什么是?用来让两个表的数据之间建立链接,保证数据的一致性和完整性。
语法:
实操:将下面的员工表和部门表联系起来
SELECT * FROM emp;
INSERT INTO emp (id,name,joindata,salary,bonus) VALUES(1,'张三','2022-12-12',8000,1000);
INSERT INTO emp (id,name,joindata,salary,bonus) VALUES(0,'李四','2022-12-12',8000,1000);
INSERT INTO emp (id,name,joindata,salary,bonus) VALUES(0,'王五','2022-12-12',8000,1000);
ALTER TABLE emp ADD dep_id INT;
UPDATE emp SET dep_id=1 WHERE `name` = '张三';
UPDATE emp SET dep_id=1 WHERE `name` = '李四';
UPDATE emp SET dep_id=2 WHERE `name` = '王五';
CREATE TABLE dept(
id int PRIMARY KEY auto_increment,
dep_name varchar(20) UNIQUE,
addr varchar(20)
);
SELECT * FROM dept;
INSERT INTO dept (id,dep_name,addr) VALUES(0,'研发部','广州');
INSERT INTO dept (id,dep_name,addr) VALUES(0,'销售部','深圳');
注意
从表中的添加外键约束,所以从表要建立在主表之后,也就是先创建主表,再创建从表。
通过以上的命令建立外键后,可以发现,此时我们再去删除dept表中的数据就会报错:
而且可以再表对象中通过逆向到表模型看到两个表之间建立了外键约束
通过以下命令可以删除外键:
ALTER TABLE emp DROP FOREIGN KEY ky_tem_dept
运行之后我们可以看到dept中的数据我可以删除了:
数据库设计
简介
软件研发的步骤
数据库设计概念
●数据库设计就是根据业务系统的具体需求,结合我们所选用的DBMS,为这个业务系统构造出最优的数据存储模型。
●建立数据库中的表结构以及 表与表之间的关联关系的过程。
●有哪些表?表里有哪些字段?表和表之间有什么关系?
数据库设计的步骤
①需求分析(数据是什么?数据具有哪些属性?数据与属性的特点是什么)
②逻辑分析(通过ER图对数据库进行逻辑建模,不需要考虑我们所选用的数据库管理系统)
③物理设计(根据数据库自身的特点把逻辑设计转换为物理设计)
④维护设计(1.对新的需求进行建表; 2.表优化)
一对多(多对一)
例如:
实现一对多的方式?
多的一方作为从表,建立外键,连接主表,比如先建立部门表,然后员工表在创建的时候建立外键。
多对多
实现多对多的方式?
创建一个中间表,表有两个键,去连接另外两个表的主键
一对一
多表查询
如果我们直接用以下语句查询emp和dept
SELECT * FROM emp,dept;
我们可以发现查询出来的结果是这样的:
可以发现查询出来的表有无效的情况,这种现象称为笛卡尔积,取了两个集合所有的组合情况。
多表查询就是为了消除无效数据的情况
内连接
可以怎么做?
可以将两个表之间对应的列的关系写到查询条件中来,比如上表中的员工表中的dep_id其实是和部门表中的id是对应的,那么我们可以这样写:
SELECT * FROM emp,dept where emp.dep_id = dept.id
以上就是内连接的使用方法,它是查询两表相交集的部分。
内连接的语法有两种:
上面的例子就是使用的隐式内连接,它还有以下的用法:
1.只想显示我们想要的两表中的某些字段
SELECT emp.name,dept.dep_name FROM emp,dept WHERE emp.dep_id = dept.id;
2.可以给表起别名,比如emp为T1,dept为T2,效果也是一样的
SELECT T1.name,T2.dep_name FROM emp T1,dept T2 WHERE T1.dep_id = T2.id;
以下式显示内连接的用法:
SELECT emp.name,dept.dep_name FROM emp INNER JOIN dept ON emp.dep_id = dept.id;
外连接
左外连接
查询A表所有数据和交集部分数据
SELECT 字段列表 FROM 表1 LEFT OUTER JOIN 表2 ON 条件;
eg:查询emp表所有数据和对应的部门信息
SELECT * FROM emp LEFT JION OUTER dept ON emp.dep_id = dept.id;
右外连接
查询B表所有数据和交集部分数据
SELECT 字段列表 FROM 表1 RIGHT OUTER JOIN 表2 ON 条件;
子查询
单行单列
SELECT 字段 FROM 表 WHERE 字段 条件运算符 (子查询);
eg:
多行单列
SELECT 字段 FROM 表 WHERE 字段名 in (子查询);
例如:
多行多列
SELECT 字段列表 FROM (子查询) WHERE 条件
事务
事务简介
事务的三个命令
开启:begin
提交:commit
回滚:rollback
eg:一个转账的操作,张三和李四都有1000块,现在张三给李四转500块。
我们新建查询:
正常的转账流程:
-- 张三转500
UPDATE trans_money SET trans_money.money = trans_money.money - 500 WHERE trans_money.`name` = '张三';
-- 李四收500
UPDATE trans_money SET trans_money.money = trans_money.money + 500 WHERE trans_money.`name` = '李四';
但是如果在执行事务中出错:
-- 张三转500
UPDATE trans_money SET trans_money.money = trans_money.money - 500 WHERE trans_money.`name` = '张三';
出错啦!!
-- 李四收500
UPDATE trans_money SET trans_money.money = trans_money.money + 500 WHERE trans_money.`name` = '李四';
这时,前面张三已经转了500,但李四没有收到,这时造成数据库中的数据混乱。
如果我们这时用事务命令去控制事务,就能解决这个问题:
首先按用begin开始事务:
begin
然后再去执行错误转账操作:
UPDATE trans_money SET trans_money.money = trans_money.money - 500 WHERE trans_money.name = '张三';
出错啦!!
-- 李四收500
UPDATE trans_money SET trans_money.money = trans_money.money + 500 WHERE trans_money.name = '李四';
可以看到虽然报错但是第一个转出500执行成功了:
我们去看表中的内容也发生了变化:
但是开启begin事务后的这种变化只是临时的,我们从另一个观察者处可以看到数据并没有变化:
数据出错后我们可以进行回滚事务:rollback,可以看到数据又恢复到事务操作之前。
数据在提交之前都是暂时的,只有提交了commit才能真正的结束事务,保存数据。
commit
事务的四大特征
面试
ACID
1.原子性(Atomicity) :事务是不可分割的最小操作单位,要么同时成功,要么同时失败
2.一致性(Consistency) :事务完成时,必须使所有的数据都保持一 致状态
3.隔离性(Isolation) :多个事务之间, 操作的可见性
4.持久性(Durability) :事务- -旦提交或回滚, 它对数据库中的数据的改变就是永久的
- 一个注意点,MYSQL中的事务默认是自动提交的。oracle是手动提交
我们之前写的每一条语句其实就是相当于一个事务,执行完毕之后,表内的数据都会永久性的改变
查询事务的默认提交方式的语句是:
SELECT @@autocommit;
值=1:默认提交
值=0:手动提交