视图:是一种虚拟存在的数据表,这个虚拟表并不在数据库中实际存在。
作用:将一些较为复杂的查询语句的结果,封装到一个虚拟表中,后期再有相同需求时,直接查询该虚拟表即可。
-- 视图
CREATE DATABASE db0809pm;
USER db0809pm;
CREATE TABLE country(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(30)
);
INSERT INTO country VALUES (NULL,'中国'),(NULL,'美国'),(NULL,'俄罗斯');
CREATE TABLE city(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(30),
cid INT,`country`
CONSTRAINT cc_fk1 FOREIGN KEY (cid) REFERENCES country(id)
);
INSERT INTO city VALUES (NULL,'beijing',1),(NULL,'shanghai',1),(NULL,'niuy',2),(NULL,'莫斯科',3);
-- 创建city_ country视图,保存城市和国家的信息(使用指定列名)
CREATE VIEW city_country (city_id,city_name,country_name) AS
SELECT
c1.id,
c1.name,
c2.name
FROM
city c1,
country c2
WHERE
c1.id=c2.id;
-- 查询视图
SELECT * FROM city_country;
-- 修改视图数据,将北京修改为深圳。(注意:修改视图数据后,源表中的数据也会随之修改)
UPDATE city_country SET city_name='深圳' WHERE city_name='beijing';
-- 将视图中的country_ name修 改为name
ALTER VIEW city_country (city_id,city_name,NAME) AS
SELECT
c1.id,
c1.name,
c2.name
FROM
city c1,
country c2
WHERE
c1.id=c2.id;
-- 删除视图
DROP VIEW IF EXISTS city_country;
存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句的集合。
存储过程和函数的好处
提高代码的复用性。
减少数据在数据库和应用服务器之间的传输,提高效率。
减少代码层面的业务处理。
类似与java中的方法
存储过程和函数的区别
存储函数必须有返回值。
存储过程可以没有返回值。
CREATE TABLE student(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
age INT,
gender VARCHAR(5),
score INT
);
INSERT INTO student VALUES(NULL,'张三',23,'男',95),(NULL,'lisi',24,'男',98),
(NULL,'wangwu',25,'女',100),(NULL,'zhaoliu',26,'女',90);
-- 按照性别进行分组,查询每组学生的总成绩。按照总成绩的升序排序
SELECT gender,SUM(score) getSum FROM student GROUP BY gender ORDER BY getSum ASC;
-- 创建stu_ group()存储过程,封装分组查询总成绩,并按照总成绩升序排序的功能
DELIMITER $
CREATE PROCEDURE stu_group()
BEGIN
SELECT gender,SUM(score) getSum FROM student GROUP BY gender ORDER BY getSum ASC;
END$
DELIMITER ;
-- 调用stu_ group()存储过程
CALL stu_group();
-- 杳看db6数掘库中所有的存储讨程
SELECT * FROM mysql.proc WHERE db='db0809pm';
-- 删除储存过程
DROP PROCEDURE IF EXISTS stu_group;
-- 定义一个int类型变量,并赋默认值为10
DELIMITER $
CREATE PROCEDURE pro_test1()
BEGIN
-- 定义变量
DECLARE num INT DEFAULT 10;
-- 使用变量
SELECT num;
END$
DELIMITER ;
-- 调用pro_ test1存 储过程
CALL pro_test1();
-- 定义一个varchar类型变量并赋值
DELIMITER $
CREATE PROCEDURE pro_test2()
BEGIN
-- 定义变量
DECLARE NAME VARCHAR(10);
-- 为变量赋值
SET NAME = '存储过程';
-- 使用变量
SELECT NAME;
END$
DELIMITER ;
-- 调用pro_ test2存 储过程
CALL pro_test2();
-- 定义两个Int变量,用于存储男女同学的总分数
DELIMITER $
CREATE PROCEDURE pro_test3()
BEGIN
-- 定义两个变量
DECLARE men,women INT;
-- 查询男同学的总分数,为men赋值
SELECT SUM(score) INTO men FROM student WHERE gender='男';
-- 查询女同学的总分数,为women赋值
SELECT SUM(score) INTO women FROM student WHERE gender='女';
-- 使用变量
SELECT men,women;
END$
DELIMITER ;
-- 调用pro_ test3存 储过程
CALL pro_test3();
/*
定义一个int变量,用于存储班级总成绩
定义一个varchar变量,用于存储分数描述
根据总成绩判断:
380分及以上 学习优秀
320 ~ 380 学习不错
320以下 学习一般
*/
DELIMITER $
CREATE PROCEDURE pro_test4()
BEGIN
-- 定义变量
DECLARE total INT;
DECLARE info VARCHAR(10);
-- 查询总成绩,为total赋值
SELECT SUM(score) INTO total FROM student;
-- 对总成绩判断
IF total > 380 THEN
SET info = '学习优秀';
ELSEIF total >= 320 AND total <= 380 THEN
SET info = '学习不错';
ELSE
SET info = '学习一般';
END IF;
-- 查询总成绩和描述信息
SELECT total,info;
END$
DELIMITER ;
-- 调用pro_test4储存过程
CALL pro_test4();
/*
输入总成绩变量,代表学生总成绩
输出分数描述变量,代表学生总成绩的描述信息
根据总成绩判断:
380分及以上 学习优秀
320 ~ 380 学习不错
320以下 学习一般
*/
DELIMITER $
CREATE PROCEDURE pro_test5(IN total INT,OUT info VARCHAR(10))
BEGIN
-- 对总成绩判断
IF total > 380 THEN
SET info = '学习优秀';
ELSEIF total >= 320 AND total <= 380 THEN
SET info = '学习不错';
ELSE
SET info = '学习一般';
END IF;
END$
DELIMITER ;
-- 调用pro test5存 储过程
CALL pro_test5(383,@info);
CALL pro_test5((SELECT SUM(score) FROM student),@info);
SELECT @info;
-- 计算1~100之间的偶数和
DELIMITER $
CREATE PROCEDURE pro_test6()
BEGIN
-- 定义求和变量
DECLARE result INT DEFAULT 0;
-- 定义初始化变量
DECLARE num INT DEFAULT 1;
-- while循环
WHILE num <= 100 DO
IF num % 2 = 0 THEN
SET result = result + num;
END IF;
SET num = num+1;
END WHILE;
-- 查询求和结果
SELECT result;
END$
DELIMITER ;
-- 调用pro_ test6存 储过程
CALL pro_test6();
-- 定义存储函数,获取学生表中成绩大于95分的学生数量
DELIMITER $
CREATE FUNCTION fun_test1()
RETURNS INT
BEGIN
-- 定义变量
DECLARE s_count INT;
-- 查询成绩大于95分的数量,为s_count赋值
SELECT COUNT(*) INTO s_count FROM student WHERE score>95;
-- 返回统计结果
RETURN s_count;
END$
DELIMITER ;
-- 调用函数
SELECT fun_test1();
-- 删除函数
DROP FUNCTION fun_test1;
-- 触发器
CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
money DOUBLE
);
-- insert into account values (null,'zhangsan',1000),(null,'lisi',1000);
-- 创建日志表account_log
CREATE TABLE account_log(
id INT PRIMARY KEY AUTO_INCREMENT, -- 日志id
operation VARCHAR(20), -- 操作类型
operation_time DATETIME,
operation_id INT, -- 操作表的id
operation_params VARCHAR(200) -- 操作参数
);
-- 创建INSERT型触发器。用于对account表新增数据进行日志的记录’
DELIMITER $
CREATE TRIGGER acccount_insert
AFTER INSERT
ON account
FOR EACH ROW
BEGIN
INSERT INTO account_log VALUES (NULL,'INSERT',NOW(),new.id,CONCAT('插入后{id=',new.id,',name=',new.name,',money=',new.money,'}'));
END$
DELIMITER ;
-- 向account表添加一条记录
INSERT INTO account VALUES (NULL,'wangwu',2000);
-- 查询account表
SELECT * FROM account;
-- 查询account_ log表
SELECT * FROM account_log;
-- 创建UPDATE型触发器。用于对account表修改数据进行日志的记录
DELIMITER $
CREATE TRIGGER account_update
AFTER UPDATE
ON account
FOR EACH ROW
BEGIN
INSERT INTO account_log VALUES (NULL,'UPDATE',NOW(),new.id,CONCAT('更新前{id=',old.id,',name=',old.name,',money=',old.money,'}','更新后{id=',new.id,',name=',new.name,',money=',new.money,'}'));
END$
DELIMITER ;
UPDATE account SET money=2000 WHERE account.name='lisi';
SELECT * FROM account;
SELECT * FROM account_log;
-- 创建DELETE型触发器。用于对account表删除数据进行日志的记录
DELIMITER $
CREATE TRIGGER account_delete
AFTER DELETE
ON account
FOR EACH ROW
BEGIN
INSERT INTO account_log VALUES (NULL,'DELETE',NOW(),old.id,CONCAT('删除前{id=',old.id,',name=',old.name,',money=',old.money,'}'));
END$
DELIMITER ;
DELETE FROM account WHERE account.name='wangwu';
SELECT * FROM account;
SELECT * FROM account_log;
-- 查看触发器
SHOW TRIGGERS;
-- 删除acccount_insert触发器
DROP TRIGGER acccount_insert;
事务:一条或多条SQL语句组成一一个执行单元,其特点是这个单元要么同时成功要么同时失败。
单元中的每条SQL语句都相互依赖,形成一个整体。
如果某条SQL语句执行失败或者出现错误,那么整个单元就会撤回到事务最初的状态。
如果单元中所有的SQL语句都执行成功,则事务就顺利执行。
开启事务:
START TRANSACTION;
回滚事务:
ROLLBACK;
提交事务:
COMMIT;
-- 事务
-- 张三个李四转账500
-- 开启事务
START TRANSACTION;
-- zhangsan-500
UPDATE account SET money=money-500 WHERE NAME='zhangsan';
-- chucuo
-- 暂时储存,如果不提交,关闭mysql连接过后再重新打开,数据库里面的数据不会发生变化
-- lisi+500
UPDATE account SET money=money+500 WHERE NAME='lisi';
-- 回滚事务
ROLLBACK;
-- 提交事务
COMMIT;
事务提交方式的分类
自动提交(MySQL默认)。
手动提交。
查看事务提交方式
SELECT @@AUTOCOMMIT;
修改事务提交方式
SET @@AUTOCOMMIT=数字;
/*
查询事务提交方式: SELECT @@AUTOCOMMIT;
1代表自动提交 0代表手动提交
修改事务提交方式:SET @QAUTOCOMMIT=数字;
*/
-- 查询事务的提交方式
SELECT @@autocommit;
-- 修改事务的提交方式
SET @autocommit = 0;
原子性(Atomicity)
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。
因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
一致性(Consistency)
一致性是指事务必须使数据库从一一个一致性状态变换到另一个一 致性状态。
也就是说一个事务执行之 前和执行之后都必须处于致性状态。
隔离性(isolcation)
隔离性是当多个用户并发访问数据库时,比如操作同一张表时 ,数据库为每一个用户开启事务。
不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
持久性(durability)
持久性是指一个事务一-旦被提交 了, 那么对数据库中的数据的改变就是永久性的。
即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
-- 查询事务隔离级别
SELECT @@tx_isolation;
-- 修改事务隔离级别(修改后需要重新连接)
SET clobal TRANSACTION ISOLATION LEVEL READ COMMITTED;
MySQL数据库使用不同的机制存取表文件,包括存储方式、引技巧、锁定水平等不同的功能。这些不同的技术以及配套的功能称为存储弓|擎。
Oracle、SqIServer 等数据库只有一种存储引擎。而MySQL针对不同的需求,配置不同的存储引擎就会让数据库采取不同处理数据的方式和扩展功能。
MySQL支持的存储引擎有很多, 常用的有三种: InnoDB、MyISAM、 MEMORY。
特性对比
MylSAM存储引擎:访问快,不支持事务和外键操作。
InnoDB存储引擎:支持事务和外键操作,支持并发控制,占用磁盘空间大。(MySQL 5.5版本后默认)
MEMORY存储引擎:内存存储,速度快,不安全。适给小量快速访问的数据。
SHOW ENGINES;
SHOW TABLE STATUS FROM db0809pm;
SHOW TABLE STATUS FROM db0809pm WHERE NAME = 'account';
CREATE TABLE engine_test(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10)
)ENGINE = INNODB;
ALTER TABLE engine_test ENGINE = MYISAM;
MyISAM
特点:不支持事务和外键操作。读取速度快,节约资源。
使用场景:以查询操作为主,只有很少的更新和删除操作,姐对事务的完整性、并发性要求不是很高!
InnoDB
特点: MySQL的默认存储引擎,支持事务和外键操作。
使用场景:对事务的完整性有比较高的要求,在并发条件下要求数据的一致性,读写频繁的操作!
MEMORY
特点:将所有数据保存在内存中,在需要快速定位记录和其他类似数据环境下,可以提供更快的访问。
使用场景:通常用于更新不太频繁的小表,用来快速得到访问的结果!
总结:针对不同的需求场景,来选择最适合的存储|擎即呵!如果不确定、则使用数据库默认的存储引擎!
MySQL索引:是帮助MySQL高效获取数据的一种数据结构。所以,索引的本质就是数据结构!
在表数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式指向数据,这样就可以在这些数据结构上实现高级查找算法这种数据结构就是索引。
按照功能分类
普通索引:最基本的索引,没有任何限制。
唯一索引:索引列的值必须唯一, 但允许有空值。如果是组合索引,则列值组合必须唯一。
主键索引:一种特殊的唯一索引, 不允许有空值。在建表时有主键列同时创建主键索弓l。
联合索列:顾名思义,就是将单列索弓l进行组合。
外键索引:只贿InnoDB引擎支持外键索引,用来保证数据的一致性、完整性和实现级联操作。
全文索引:快速匹配全部文档的方式。InnoDB 引擎5.6版本后才支持全文索引。MEMORY 引擎不支持。
按照结构分类
BTree索引: MySQL使用最频繁的一个索引数据结构,是InnoDB和MylSAM存储引擎默认的索引类型,底层基于B+Tree数据结构。
Hash索引: MySQL中Memory存储引擎默认支持的索引类型。
-- 为student表中的name列创建一个普通索引
CREATE INDEX idx_name ON student(NAME);
-- 为student表中的age列创建一个唯一索引
CREATE UNIQUE INDEX idx_age ON student(age);
-- 查询student表中的索引 (主键列目带主键索引)
SHOW INDEX FROM student;
-- 查询db0809数据库中的product表(外键列自带外键索引)
SHOW INDEX FROM product;
索引是在存储引擎中实现的,不同的存储弓擎所支持的索引也不一样,这里我们主要介绍InnoDB引擎的BTree索引。
BTree索引类型是基于B+Tree数据结构的,而B+Tree数据结构又是BTree数据结构的变种。通常使用在数据库和操作系统中的文件系统,特点是能够保持数据稳定有序。
需要理解的B+Tree和BTree的区别
系统从磁盘读取数据到内存时是以磁盘块( block )为基本单位的。
位于同一个磁盘块中的数据会被一次性读取出来 ,而不是需要什么取什么。
InnoDB存储引擎中有页( Page )的概念,页是其磁盘管理的最小单位。InnoDB 存储弓|擎中默认每个页的大小为16KB。
InnoDB弓|擎将若干个地址连接磁盘块,以此来达到页的大小16KB ,在查询数据时如果一个页中的每条数据都能有 助于定位
数据记录的位置,这将会减少磁盘I/O次数,提高查询效率。
在每一个结点上除了去保存键值以外,还会去保存真实的数据,在进行查询数据时,只要涉及到相应的磁盘块,那这些数据也会被全部读取出来,所以效率不是很高。
B+Tree特点:在分支结点上只保存键值,并没有真实的数据,真实的数据只会保存在叶子结点上
在磁盘块上并没有涉及到IO操作,提高了查询的特点
叶子结点之间进行连接,方便进行范围的查询
BTree数据结构
每个节点中不仅包含key值,还有数据。会增加查询数据时磁盘的I0次数。
B+Tree数据结构
非叶子节点只存储key值。
所有数据存储在叶子节点。
所有叶子节点之间都有连接指针。
B+Tree好处
提高查询速度。
减少磁盘的I0次数。
树型结构较小。
创建索引遵循的原则
1.对查询频次较高,且数据量比较大的表建立索弓|。
2.使用唯一索引,区分度越高,使用索引|的效率越高。
3.索引字段的选择,最佳候选列应当从where子句的条件中提取。
4.虽然可以有效的提升查询数据的效率 ,但并不是多 多益善。