04、MySQL(事务、权限、视图)
11、事务【重点】
11.1、模拟转账
生活当中转账是转账方账户扣钱,收账方账户加钱。我们用数据库操作来模拟现实转账。
CREATE TABLE account ( id INT, `name` VARCHAR(16), money INT ) INSERT INTO account (id,NAME,money) VALUE (1,'xiaosan',1000); INSERT INTO account (id,NAME,money) VALUE (2,'xiaoming',1000);
11.1.1、数据库模拟转账
#A账户转账给B账户1000元。
#A账户减1000元 UPDATE account SET MONEY = MONEY-1000 WHERE id=1; #B账户加1000元 UPDATE account SET MONEY = MONEY+1000 WHERE id=2;
上述代码完成了两个账户之间转账的操作。
11.1.2、模拟转账错误
#A账户转账给B账户1000元。 #A账户减1000元 UPDATE account SET MONEY =MONEY-1000 WHERE id=1; #断电、异常、出错... #B账户加1000元 UPDATE account SET MONEY = MONEY+1000 WHERE id=2;
上述代码在减操作后过程中出现了异常或加钱语句出错,会发现,减钱仍旧是成功的,而加钱失败了!
注意: 每条SQL语句都是一个独立的操作,一个操作执行完对数据库是永久性的影响。
11.2、事务的概念
事务是一个原子操作。是一个最小执行单元。可以由一个或多个SQL语句组成,在同一个事务当中,所有的SQL语句都成功执行时,整个事务成功,有一个SQL语句执行失败,整个事务都执行失败。
11.3、事务的边界
开始: 连接到数据库,执行一条DML语句。上一个事务结束后,又输入了一条DML语句,即事务的开始
结束:
1)提交:
a.显示提交:commit;
b.隐式提交:一条创建、删除的语句,正常退出(客户端退出连接);
2)回滚:
a.显示回滚:rollback;
b.隐式回滚:非正常退出(断电、宕机),执行了创建、删除的语句,但是失败了,会为这个无效的语句执行回滚。
11.4、事务的原理
数据库会为每一个客户端都维护一个空间独立的缓存区(回滚段),一个事务中所有的增删改语句的执行结果都会缓存在回滚段中,只有当事务中所有SQL语句均正常结束(commit),才会将回滚段中的数据同步到数据库。否则无论因为哪种原因失败,整个事务将回滚(rollback)。
11.5、事务的特性
Atomicity(原子性)
表示一个事务内的所有操作是一个整体,要么全部成功,要么全部失败
Consistency(一致性)
表示一个事务内有一个操作失败时,所有的更改过的数据都必须回滚到修改前状态
lsolation(隔离性)
事务查看数据操作时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。
Durability(持久性)
持久性事务完成之后,它对于系统的影响是永久性的。
11.6、事务应用
应用环境: 基于增删改语句的操作结果(均返回操作后受影响的行数),可通过程序逻辑手动控制事务提交或回滚
11.6.1、事务完成转账
#A账户给B账户转账。 #1.开启事务 START TRANSACTION; SET autocommit =0;#禁止自动提交setAutoCommit=1;#开启自动提交 #2.事务内数据操作语句 UPDATE `account` SET MONEY = `money`-1000 WHERE ID =1; UPDATE `account` SET MONEY = `moneys`+1000 WHERE ID = 2; #3.事务内语句都成功了,执行 COMMIT; COMMIT; #4.事务内如果出现错误,执行 ROLLBACK; ROLLBACK;
注意∶开启事务后,执行的语句均属于当前事务,成功再执行COMIIT,失败要进行ROLLBACK
12、权限管理
12.1、创建用户
CREATE USER 用户名 IDENTIFIED BY 密码
12.1.1、创建一个用户
#创建一个 xiaohe 用户 CREATE USER `xiaohe` IDENTIFIED BY '123456';
12.2、授权
GRANT ALL ON 数据库.表 TO 用户名;
12.2.1、用户授权
#将companyDB下的所有表的权限都赋给xiaohe GRANT ALL ON companyDB.* TO 'xiaohe';
12.3、撤销权限
REVOKE ALL ON 数据库.表名 FROM 用户名
·注意: 撤销权限后,账户要重新连接客户端才会生效
12.3.1、撤销用户权限
#将xiaohe的companyDB的权限撤销 REVOKE ALL ON companyDB.* FROM `xiaohe`;
12.4、删除用户
DROP USER 用户名
12.4.1、删除用户
#删除用户 xiaohe DROP USER `xiaohe`;
13、视图
13.1、概念
视图,虚拟表,从一个表或多个表中查询出来的表,作用和真实表一样,包含一系列带有行和列的数据。视图中,用户可以使用SELECT语句查询数据,也可以使用INSERT,UPDATE,DELETE修改记录,视图可以使用户操作方便,并保障数据库系统安全。
13.2、视图特点
优点
简单化,数据所见即所得。
安全性,用户只能查询或修改他们所能见到得到的数据。
逻辑独立性,可以屏蔽真实表结构变化带来的影响。
·缺点
性能相对较差,简单的查询也会变得稍显复杂。
修改不方便,特变是复杂的聚合视图基本无法修改。
13.3、视图的创建
13.3.1、创建视图
语法: CREATE VIEW 视图名 AS 查询数据源表语句;
#创建 t_empInfo 的视图,其视图从 t_employees 表中查询到员工编号、员工姓名、员工邮箱、工资 CREATE VIEW t_empInfo AS SELECT EMPLOYEE_ID,FIRST_NAME,LAST_NAME,EMAIL,SALARY FROM t_employees;
13.3.2、使用视图
#查询t_empInfo视图中编号为101的员工信息 SELECT * FROM t_empInfo WHERE employee_id = '101';
13.4、视图的修改
方式一: CREATE OR REPLACE VIEW 视图名 AS 查询语句
方式二: ALTER VIEW 视图名 AS 查询语句
13.4.1、修改视图
#方式1:如果视图存在则进行修改,反之,进行创建 CREATE OR REPLACE VIEW t_empInfo AS SELECT EMPLOYEE_ID,FIRST_NAME, LAST_NAME ,EMAIL ,SALARY ,DEPARTMENT_ID FROM t_employees; #方式2:直接对已存在的视图进行修改 ALTER VIEW t_empInfo AS SELECT EMPLOYEE_ID,FIRST_NAME,LAST_NAME,EMAIL,SALARY FROM t_employees;
13.5、视图的删除
DROP VIEW 视图名
13.5.1、删除视图
#删除t_empInfo视图 DROP VIEW t_empInfo;
注意: 删除视图不会影响原表
13.6、视图的注意事项
注意:
视图不会独立存储数据,原表发生改变,视图也发生改变。没有优化任何查询性能。
如果视图包含以下结构中的一种,则视图不可更新
聚合函数的结果
DISTINCT 去重后的结果
GROUP BY分组后的结果
HAVING筛选过滤后的结果
UNION、 UNION ALL 联合后的结果
14、SQL语言分类
14.1、SQL语言分类
数据查询语言DQL (Data Query Language): select、where、order by、group by、having 。
数据定义语言DDL (Data Definition Language) : create、alter、drop。
数据操作语言DML (Data Manipulation Language) : insert、update、delete 。
事务处理语言TPL (Transaction Process Language) : commit、rollback 。
数据控制语言DCL (Data Control Language): grant、revoke。
15、综合练习
15.1、数据库表
#创建用户表 CREATE TABLE USER( userId INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR (20)NOT NULL, PASSWORD VARCHAR(18)NOT NULL, address VARCHAR(100), phone VARCHAR(11) ); #创建分类表 CREATE TABLE category( cid VARCHAR(32) PRIMARY KEY , cname VARCHAR(100) NOT NULL#分类名称 ); #商品表 CREATE TABLE `products`( pid VARCHAR(32) PRIMARY KEY, `name` VARCHAR(40), price DOUBLE(7,2), category_id VARCHAR(32), CONSTRAINT fk_products_category_id FOREIGN KEY(category_id) REFERENCES category(cid) ); #订单表 CREATE TABLE `orders`( `oid` VARCHAR(32) PRIMARY KEY, `totalprice` DOUBLE(12,2), #总计 `userId` INT, CONSTRAINT fk_orders_userId FOREIGN KEY(userId) REFERENCES USER(userId)#外键 ); #订单项表 CREATE TABLE orderitem( oid VARCHAR(32),#订单id pid VARCHAR(32),#商品id num INT, #购买商品数量 PRIMARY KEY(oid, pid),#主键 CONSTRAINT fk_orderitem_oid FOREIGN KEY(oid) REFERENCES orders(oid), CONSTRAINT fk_orderitem_pid FOREIGN KEY(pid) REFERENCES products(pid) ); #初始化数据 #用户表添加数据 INSERT INTO USER(username ,PASSWORD, address, phone) VALUES('张三','123','北京昌平沙河','13812345678'); INSERT INTO USER(username , PASSWORD, address, phone) VALUES('王五', '5678','北京海淀','13812345141'); INSERT INTO USER(username , PASSWORD , address , phone)VALUES('赵六','123','北京朝阳','13812340987'); INSERT INTO USER(username , PASSWORD , address , phone) VALUES('田七', '123','北京大兴','13812345687'); #给分类表初始化数据 INSERT INTO category VALUES( 'c001','电器'); INSERT INTO category VALUES( 'c002','服饰'); INSERT INTO category VALUES('c003','化妆品'); INSERT INTO category VALUES( 'c004','书籍'); #给商品表初始化数据 INSERT INTO products(pid , NAME , price,category_id) VALUES( 'p001','联想' , 5000, 'c001'); INSERT INTO products(pid , NAME, price,category_id) VALUES('p002','海尔', 3000 , 'c001'); INSERT INTO products(pid , NAME ,price,category_id) VALUES( 'p003','雷神',5000, 'c001'); INSERT INTO products(pid , NAME,price,category.id) VALUES('p004','JACK JONES' , 800 'c002'); INSERT INTO products(pid , NAME , price,category_id) VALUES( 'p005','真维斯',200, 'c002'); INSERT INTO products(pid , NAME , price, category_id) VALUES( 'p006','花花公子',440, 'c002'); INSERT INTO products(pid ,NAME,price,category_id) VALUES( 'p007','劲霸' ,2000,'c002'); INSERT INTO products(pid,NAME, price,category_id) VALUES( 'p008','香奈儿' ,800,'c003'); INSERT INTO products(pid , NAME , price,category_id) VALUES( 'p009','相宜本草' ,200,'c003'); INSERT INTO products(pid , NAME ,price,category_id) VALUES( 'p010','梅明子',200,NULL); #添加订单 INSERT INTO orders VALUES ( 'o6100' , 18000.50,1); INSERT INTO orders VALUES( 'o6101',7200.35,1); INSERT INTO orders VALUES( 'o6102',600.00,2); INSERT INTO orders VALUES ( 'o6103' , 1300.26,4); #订单详情表 INSERT INTO orderitem VALUES( 'o6100','p001',1), ( 'o6100','p002',1),( 'o6101','p003',1);
15.2、综合练习1-【多表查询】
15.2.1、查询所有用户的订单
SELECT o.oid, o.totalprice,u.userId, u.username , u.phone FROM orders o INNER JOIN USER u ON o.userId=u.userId;
15.2.2、查询用户id为1的所有订单详情
SELECT o.oid,o.totalprice,u.userId,u.username,u.phone,oi.pid FROM orders o INNER JOIN USER u ON o.userId = u.userId INNER JOIN orderitem oi ON o.oid=oi.oid WHERE u.userid=1;
15.3、综合练习2-【子查询】
15.3.1、查看用户为张三的订单
SELECT * FROM orders WHERE userId=(SELECT userid FROM USER WHERE username='张三');
15.3.2、查询出订单的价格大于800的所有用户信息。
SELECT * FROM USER WHERE userId IN(SELECT DISTINCT userId FROM orders WHERE totalprice> 800);
15.4、综合练习3-【分页查询】
15.4.1、查询所有订单信息,每页显示5条数据
#查询第一页 SELECT * FROM orders LIMIT 0,5;

浙公网安备 33010602011771号