zoukankan      html  css  js  c++  java
  • MySql笔记二——约束&事务

    一、约束

    1、概念:对表中的数据进行限定,保证数据的正确性、有效性和完整性。

    2、分类:

    1. 主键约束:primary key
    • 含义:非空且唯一
    • 一张表只能有一个字段为主键
    • 主键就是表中记录的唯一标识
    1. 非空约束:not null
      • 值不能为null
    2. 唯一约束:unique
      • 值不能重复
      • MySql中唯一约束限定的列的值可以有多个null
    3. 外键约束:foreign key
      • 让表于表产生关系,从而保证数据的正确性。(阿里规范:不得使用外键与级联,一切外键概念必须在应用层解决)

    3、语法

    1、主键约束语法

    1、创建表时添加

    在创建表时,添加主键约束
    		create table 表名(
    			id int primary key,-- 给id添加主键约束
    			name varchar(20)
    		);
    

    2、创建表后添加

    语法:
    ALTER TABLE 表名 add primary key(字段名);
    
    举例:
    ALTER TABLE stu add primary key(id);
    

    3、删除主键

    ALTER TABLE 表名 DROP PRIMARY KEY;
    

    4、自动增长

    概念:如果某一列是数值类型的,使用 auto_increment 可以来完成值得自动增长

    1. 在创建表时,添加主键约束,并且完成主键自增长
    		create table stu(
    			id int primary key auto_increment,-- 给id添加主键约束
    			name varchar(20)
    		);
    		
    2.创建表后添加
    	ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;
    	
    3. 删除自动增长
    	ALTER TABLE stu MODIFY id INT;
    

    2、唯一约束

    1、创建表时添加约束

    CREATE TABLE stu(
    			id INT,
    			phone_number VARCHAR(20) UNIQUE -- 添加了唯一约束
    		
    		);
    * 注意mysql中,唯一约束限定的列的值可以有多个null
    

    2、创建表后添加约束

    ALTER TABLE 表名 add unique(字段名);
    

    3、删除唯一约束

    1.先查看约束名
    show create table 表名;
    
    2.找到唯一约束名,然后删除
    ALTER TABLE 表名 DROP INDEX 约束名;
    

    3、外键约束

    1、创建表时添加约束

    create table 表名(
    				....
    				外键列
    				constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称)
    			);
    

    2、创建表后添加约束

    ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);
    

    3、删除非空约束

    ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
    

    2、非空约束语法

    1、创建表时添加约束

    CREATE TABLE stu(
    			id INT,
    			NAME VARCHAR(20) NOT NULL -- name为非空
    		);
    

    2、创建表后添加约束

    ALTER TABLE 表名 MODIFY 字段名 字段类型 NOT NULL;
    

    3、删除非空约束

    ALTER TABLE 表名 MODIFY 字段名 字段类型;
    

    5、级联操作

    用于操作具有外键关系的表,使其级联更新或级联删除。(阿里规范:不得使用外键与级联,一切外键概念必须在应用层解决)

    1、添加级联

    LTER TABLE 表名 ADD CONSTRAINT 外键名称 
    					FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称) ON UPDATE CASCADE ON DELETE CASCADE  ;
    

    2、分类

    • 级联更新:ON UPDATE CASCADE
    • 级联删除:ON DELETE CASCADE

    二、数据库的设计

    2.1 多表之间的关系

    1、多表之间的关系分类

    • 一对一(了解)

      如:人和身份证

      分析:一个人只有一个身份证,一个身份证只能对应一个人

    • 一对多(多对一):

      如:部门和员工

      分析:一个部门有多个员工,一个员工只能对应一个部门

    • 多对多:

      如:学生和课程

      分析:一个学生可以选择很多门课程,一个课程也可以被很多学生选择

    2、实现关系

    • 一对一实现方式:一对一关系实现,可以在任意一方添加唯一外键指向另一方的主键。
    • 一对多实现方式:在多的一方建立外键,指向一的一方的主键
    • 多对多实现方式:多对多关系实现需要借助第三张中间表。中间表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键

    3、小练习

    -- 创建旅游线路分类表 tab_category
    		-- cid 旅游线路分类主键,自动增长
    		-- cname 旅游线路分类名称非空,唯一,字符串 100
    		CREATE TABLE tab_category (
    			cid INT PRIMARY KEY AUTO_INCREMENT,
    			cname VARCHAR(100) NOT NULL UNIQUE
    		);
    		
    		-- 创建旅游线路表 tab_route
    		/*
    		rid 旅游线路主键,自动增长
    		rname 旅游线路名称非空,唯一,字符串 100
    		price 价格
    		rdate 上架时间,日期类型
    		cid 外键,所属分类
    		*/
    		CREATE TABLE tab_route(
    			rid INT PRIMARY KEY AUTO_INCREMENT,
    			rname VARCHAR(100) NOT NULL UNIQUE,
    			price DOUBLE,
    			rdate DATE,
    			cid INT,
    			FOREIGN KEY (cid) REFERENCES tab_category(cid)
    		);
    		
    		/*创建用户表 tab_user
    		uid 用户主键,自增长
    		username 用户名长度 100,唯一,非空
    		password 密码长度 30,非空
    		name 真实姓名长度 100
    		birthday 生日
    		sex 性别,定长字符串 1
    		telephone 手机号,字符串 11
    		email 邮箱,字符串长度 100
    		*/
    		CREATE TABLE tab_user (
    			uid INT PRIMARY KEY AUTO_INCREMENT,
    			username VARCHAR(100) UNIQUE NOT NULL,
    			PASSWORD VARCHAR(30) NOT NULL,
    			NAME VARCHAR(100),
    			birthday DATE,
    			sex CHAR(1) DEFAULT '男',
    			telephone VARCHAR(11),
    			email VARCHAR(100)
    		);
    		
    		/*
    		创建收藏表 tab_favorite
    		rid 旅游线路 id,外键
    		date 收藏时间
    		uid 用户 id,外键
    		rid 和 uid 不能重复,设置复合主键,同一个用户不能收藏同一个线路两次
    		*/
    		CREATE TABLE tab_favorite (
    			rid INT, -- 线路id
    			DATE DATETIME,
    			uid INT, -- 用户id
    			-- 创建复合主键
    			PRIMARY KEY(rid,uid), -- 联合主键
    			FOREIGN KEY (rid) REFERENCES tab_route(rid),
    			FOREIGN KEY(uid) REFERENCES tab_user(uid)
    		);
    

    2.2 数据库设计的范式

    1、概念:设计数据库时,需要遵循的一些规范。要遵循后边的范式要求,必须先遵循前边的所有范式要求

    ​ 设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。

    ​ 目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。

    2、范式分类

    • 第一范式(1NF):每一列都是不可分割的原子数据项。

      • 每一列属性都是不可再分的属性值,确保每一列的原子性

      • 两列的属性相近或相似或一样,尽量合并属性一样的列,确保不产生冗余数据。

    • 第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于码(在1NF基础上消除非主属性对主码的部分函数依赖)。

      • 每一行的数据只能与其中一列相关,即一行数据只做一件事。只要数据列中出现数据重复,就要把表拆分开来。

    如上图,一个人同时订几个房间,就会出来一个订单号多条数据,这样子联系人都是重复的,就会造成数据冗余。我们应该把他拆开来。

    • 第三范式(3NF):在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)。

      • 数据不能存在传递关系,即没个属性都跟主键有直接关系而不是间接关系。像:a-->b-->c 属性之间含有这样的关系,是不符合第三范式的。

    3、扩充

    * 几个概念:
    		1. 函数依赖:A-->B,如果通过A属性(属性组)的值,可以确定唯一B属性的值。则称B依赖于A
    		
    					例如:学号-->姓名。  (学号,课程名称) --> 分数
    					
    		2. 完全函数依赖:A-->B, 如果A是一个属性组,则B属性值得确定需要依赖于A属性组中所有的属性值。
    		
    					例如:(学号,课程名称) --> 分数
    					
    		3. 部分函数依赖:A-->B, 如果A是一个属性组,则B属性值得确定只需要依赖于A属性组中某一些值即可。
    		
    					
    					例如:(学号,课程名称) -- > 姓名
    		4. 传递函数依赖:A-->B, B -- >C . 如果通过A属性(属性组)的值,可以确定唯一B属性的值,在通过B属性(属性组)的值可以确定唯一C属性的值,则称 C 传递函数依赖于A
    		
    					例如:学号-->系名,系名-->系主任
    					
    		5. 码:如果在一张表中,一个属性或属性组,被其他所有属性所完全依赖,则称这个属性(属性组)为该表的码
    		
    					例如:该表中码为:(学号,课程名称)
    					* 主属性:码属性组中的所有属性
    					* 非主属性:除过码属性组的属性
    

    4、总结

    三大范式的作用:优化数据库的结构,减少数据库的冗余。

    一范式:确定表的原子性,表中的每一列都不可再分。

    二范式:在1范式的基础上,消除表中的部分函数依赖--》需要确保表中的每一列都和主键相关,而不能只于主键中的某一部分相关。(主要针对联合主键)

    如:假设存在联合主键(a,b),其他列c,d。则该表需要满足:(a,b)-->c ,(a,b)-->d。
    
    如果出现:a-->c则该表不符合规范
    

    三范式:在2范式的基础上,消除表中的传递依赖--》需要确保表中的每一列都和主键直接相关,而不能间接相关。

    如:假设存在主键m,非主键x,y。则需要满足,m-->x	m-->y。
    
    如果出现:m-->x , x-->y 然后得出 m-->y 则该表不符合规范。
    

    如何使用三大范式去验证表设计的是否规范?

    表中的每一列都与主键或联合主键直接相关。

    其他列只与主键的某一部分相关 ×

    通过主键和非主键列确定其他列 ×

    三、事务

    事务的基本介绍

    1、什么是事务?

    事务是由单独单元的一个或多个sql组成,这个单元中的sql之间是相互依赖的。当单独单元中的一个sql发生错误,则事务失败,会将整个单元回滚到事务开始之前。当单独单元中的所有sql都执行成功,则事务会顺利进行。

    举一个不太恰当的例子,在炎热的夏天你想从冰箱拿一瓶可乐,你可以将从冰箱拿可乐看作一个事务,这个事务包括这几个操作:打开冰箱、选择可乐、关闭冰箱。如果这三个中的任何一个操作失败,你都会回到打开冰箱前的状态,如果这三个操作都成功了,你才可以喝可乐。

    2、操作

    • 开启事务:start transaction;
    • 提交事务:commit;
    • 回滚事务:rollback;

    3、例子

    CREATE TABLE account (
    			id INT PRIMARY KEY AUTO_INCREMENT,
    			NAME VARCHAR(10),
    			balance DOUBLE
    		);
    		-- 添加数据
    		INSERT INTO account (NAME, balance) VALUES ('zhangsan', 1000), ('lisi', 1000);
    		SELECT * FROM account;
    		UPDATE account SET balance = 1000;
    		-- 张三给李四转账 500 元
    		
    		-- 0. 开启事务
    		START TRANSACTION;
    		-- 1. 张三账户 -500
    		
    		UPDATE account SET balance = balance - 500 WHERE NAME = 'zhangsan';
    		-- 2. 李四账户 +500
    		-- 出错了...
    		UPDATE account SET balance = balance + 500 WHERE NAME = 'lisi';
    		
    		-- 发现执行没有问题,提交事务
    		COMMIT;
    		
    		-- 发现出问题了,回滚事务
    		ROLLBACK;
    

    4、MySQL数据库中事务默认自动提交

    5、事务提交的两种方式

    • 自动提交

      • mysql就是自动提交的
      • 一条DML(增删改)语句会自动提交一次事务。
    • 手动提交:

      • Oracle 数据库默认是手动提交事务
      • 需要先开启事务,再提交

    6、修改事务的默认提交方式

    • 查看事务的默认提交方式:SELECT @@autocommit; -- 1 代表自动提交 0 代表手动提交
    • 修改默认提交方式: set @@autocommit = 0;

    事务的ACID原则与隔离级别

    1、事务的四大特征

    • 原子性:每一个事务都是不可分割的最小操作单位,要么同时成功,要么同时失败。
    • 一致性:事务操作前后,数据总量不变。如银行转账,事务执行前后,数据的总量是一致的,不会凭空增加,也不会凭空减少。
    • 持久性:当事务提交或回滚后,数据库会持久化的保存数据。
    • 隔离性:多个事务之间,相互独立,互不干扰。

    2、事务的隔离级别

    1. 概念:多个事务之间隔离的,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题。

    2. 存在问题

      • 脏读:一个事务读取到另一个事务未提交的数据。
      • 不可重复读:一个事务读取表中的某一行数据,多次读取的结果不一致。
      • 幻读:在一个事务内读取到别的事务插入的数据,导致前后读取不一致。

    tip:

    1. 脏读和不可重复读的区别:脏读是读取前一事务未提交的数据,而不可重复读是重新读取了前一事务已提交的数据。
    2. 幻读与不可重复读的区别:不可重复读读取到的是更新(update)数据,而幻读读取到的是插入(insert)数据。

    在某些情况下,不可重复读与幻读是允许存在的,但是脏读是不允许存在的。

    1. 隔离级别

      1、read uncommitted:读未提交

      • 产生的问题:脏读、不可重复读、幻读

      2、read committed:读已提交 (Oracle)

      • 产生的问题:不可重复读、幻读

      3、repeatable read:可重复读 (MySQL默认)

      • 产生的问题:幻读

      4、serializable:串行化

      • 可以解决所有的问题
    • 注意:隔离级别从小到大安全性越来越高,但是效率越来越低
    • 数据库查询隔离级别:
      • select @@tx_isolation;
    • 数据库设置隔离级别:
      • set global transaction isolation level 级别字符串;
    * 演示:
    		set global transaction isolation level read uncommitted;
    		start transaction;
    		-- 转账操作
    		update account set balance = balance - 500 where id = 1;
    		update account set balance = balance + 500 where id = 2;
    
  • 相关阅读:
    centos 7 pip install MySQL-python 报错
    修改centos history记录数上限
    CentOS 7 如何设置为eth0网卡
    字符串判空有空格报错:binary operator expected
    Linux指定用户运行程序
    MySQL 新建用户,为用户授权,指定用户访问数据库
    解决linux 中文乱码
    UNIX目录访问操作
    通过lseek产生空洞文件
    lseek系统调用
  • 原文地址:https://www.cnblogs.com/tianwenxin/p/14193204.html
Copyright © 2011-2022 走看看