十、创建和操纵表
1、primary key关键字:指定表的主键。
2、语句格式化:忽略空格,可分行。
3、处理现有的表:一般是先删除该表在创建,否则名称相同则会覆盖原表。
如果只要在这张表不存在的时候创建,则是可以在表名后增加一个 if not exists
4、null值:没有值或缺值。
5、auto_increment:本列每增加一行时自动增量,每执行一个insert操作,自动给该列增量,给下一列赋予一个可用的值。
每个表只允许有一个auto_increment列,而且它必须被索引(如,通过使它成为主键)
last_insert_id()获取最后自动增量的id值。
6、default关键字:指定默认值。
不支持使用函数作为默认值,只支持常量。
7、引擎类型
(1)默认引擎一般是myisam。
(2)建表时指定引擎engine=语句。
(3)几个重要引擎
innodb:一个可靠额事务处理引擎,不支持全文本检索。
memory:在功能上等同于myisam,但由于数据是存储在没存(不是磁盘)中,速度很快,特别适用于临时表。
myisam:一个性能极高的引擎,支持全文本检索,但是不支持职事务处理。
MySQL所支持的引擎完整列表以及之间的差别:https://dev.mysql.com/doc/refman/5.0/en/storage_engines.html
(4)引擎类型可以混用。
(5)外键不能跨引擎。一个引擎的表不能引用使用不同引擎的表的外键。
8、alter table :更改表结构。
增加一个列:alter table A add A.b char(20)
删除一个列:alter table A drop column A.b
9、定义外键
alert table A add constraint a_A_B foreign (b) references B (b)
10、复杂的表结构更改一般需要手动删除过程
(1)用心的列布局创建一个新表
(2)使用insert select 语句把数据从旧表复制到新表,如有必要可以使用转换函数和计算字段。
(3)检验包含所需数据的新表
(4)重命名旧表(如果确定删除旧表)
(5)用旧表原来的名字重命名新表
(6)根据需要,重新创建触发器、存储过程、索引和外键。
11、使用alter 应该谨慎,最好在使用前完整备份,包括模式和数据。
12、删除表:drop table A
13、重命名表:rename A to B
十一、视图
1、视图是虚拟表,只包含使用时的动态检索数据的查询。
2、视图常见应用
(1)重用SQL语句。
(2)简化复杂的SQL操作。
(3)使用表的组成部分而不是整个表。
(4)保护数据。可以给用户授予表的特定部分访问权而不是整张表的访问权。
(5)更改数据格式和表示。
3、视图的规则和限制
(1)唯一命名(2)数目无限制(3)足够访问权限(4)可嵌套(5)可使用order by (6)不能索引,不能有关联的触发器或者默认值(7)可以和表一起使用
4、使用视图
(1)create view :创建视图
(2)show create view viewname:查看创建的视图
(3)drop view viewname:删除视图
(4)更新视图:先drop再create,或者create or replace view
5、利用视图简化复杂的联结
(1)常见应用是隐藏复杂的SQL:创建可重用的视图。
(2)重新格式化检索出来的数据,经常使用的时候,可以创建一个视图。
(3)用视图过滤不需要的数据。
(4)使用视图简化计算字段。
(5)试图可更新,删除,插入。更新一个视图就是更新基表。
(6)并非所有的视图都可以更新。
如果视图定义有以下操作,则不能进行更新:分组(使用group by 和having)、联结、子查询、并、聚集函数、distinct、导出(计算)列。
(7)视图主要用于数据检索。
十二、存储过程
1、存储过程:为以后的使用而保存的一条或者多条MySQL语句的集合。可将它视为批文件,但不仅仅限于批处理。
2、使用理由
(1)通过把处理封装在容易使用的单元中,简化复杂的操作。
(2)不要求反复建立一系列处理步骤,保证了数据的完整性。防止错误保证数据的一致性。
(3)简化对变动的处理。提高安全性,通过存储过程限制对基础数据的访问减少数据的讹误机会。
(4)提高性能。
(5)存在一些只能在单个请求中的MySQL元素和特性,存储过程可以使它们来编写更强大更灵活的代码。
3、缺点
(1)存储过程的编写比基本SQL语句复杂,编写存储过程需要更高的技能,和更丰富的经验。
(2)可没有没有创建存储过程的访问。一般管理员创建存储过程,允许用户访问,但是不允许用户创建存储过程。
4、执行存储过程:MySQL称存储过程的执行为调用,因此执行存储过程的语句为call。
(1)call接受存储过程的名字,以及传递给它的任何参数。
(2)存储过程可以显示结果也可以不显示结果。
5、创建存储过程(以之前一个项目中的例子为例)
#插入表数据 DELIMITER $$ DROP PROCEDURE IF EXISTS `add_table` ; CREATE PROCEDURE `add_table`(in TABLENAME varchar(50), ANOTHERNAME varchar(100),TABLEDESC varchar(200), CRUSER varchar(30), CRTIME datetime,OWNERTYPE int(11),OWNERID int(11)) BEGIN SELECT @TABLEINFOID:= (IFNULL(max(TABLEINFOID+1),1)) from TABLEINFO ; INSERT INTO `TABLEINFO` (`TABLEINFOID`, `TABLENAME`, `ANOTHERNAME`, `TABLEDESC`, `CRUSER`, `CRTIME`, `OWNERTYPE`, `OWNERID`) VALUES ( @TABLEINFOID, TABLENAME, ANOTHERNAME ,TABLEDESC , CRUSER , CRTIME,OWNERTYPE ,OWNERID ); END $$ DELIMITER ;
这是初始化SQL里面的一个在表‘TABLEINFO’里面插入一条数据。
(1)DELIMITER $$ :定义结束符号为$$。
MySQL中默认以;为结束符,但是存储过程要执行完整的语句,其中包含分号,因此需要重新定义一个结束符。在存储过程结束后在重新把结束符还原回来。
详细解释可参考博客:MySql中 delimiter 详解
(2)DROP PROCEDURE IF EXISTS `add_table` ;这一行语句是保证存储过程的唯一性,如果已经存在就删除该存储过程。
(3)add_table 为存储过程名称。
(4)用create procedure '存储过程名称'()语句来创建存储过程。
(5)如果存在参数,在()中列举出来,格式为(参数类型 参数 参数的数据类型)。无参数则为空。
参数类型:in 输入参数;out 输出参数;inout 输入输出参数。
详细内容可以参考博客:mysql中的存储过程之无参数,in、out、inout参数的讲解
(6)begin和end语句用来限制存储过程体。
(7)@TABLEINFOID:= (IFNULL(max(TABLEINFOID+1),1))表示定义变量;语句的意思是获取当前表最大的id,自增加一,赋予给变量TABLEINFOID,如果当前表没有数据,就把1赋予给变量。
(8)MySQL的变量都必须以@开头。
6、调用存储过程
call add_table ( 'Assessment', '评测系统', '系统', 'admin', '2017-7-31 00:00:00', 1, 1);
7、存储过程实际上是一种函数,因此需要()。
8、删除存储过程:DROP PROCEDURE IF EXISTS `add_table`。
9、参数
(1)变量:内存中一个特定的位置,用来存储临时数据。
(2)select @TABLEINFOID,可以获得当前变量的值。
10、智能建立建立存储过程
(1)comment关键字:不必须,如果给出,将在 show procedure status 的结果中展示。
(2)增加注释:在前面增加‘--’,当存储过程比较复杂的时候,注释十分必要。
(3)参数可以是布尔值,在存储过程中可以使用if语句来进行条件判断。
(4)declare:定义局部变量,指定变量名和数据类型。
(5)select a into b:把变量a的值保存到变量b中。
(6)if语句还支持elseif和else子句(牵着使用then子句,后者不使用),属于流控制语句。
(7)show procedure status:获得包括由谁创建、何时创建等详细信息的存储过程列表。
(8)限制过程状态结果:为限制其输出,可以使用like指定一个过滤模式。
example:show procedure status like‘order’;
十三、游标
1、游标:是一个存存储在MySQL服务器上的数据库查询,它不是一条select语句,而是被该语句检索出来的结果集。存储了游标之后,应用程序可以根据需要滚动或者浏览其中的数据。
2、游标主要应用于交互式应用,其中用户需要滚动屏幕上的数据,并对数据进行浏览或者进行更改。
3、MySQL游标只能用于存储过程(和函数)。
4、使用游标的步骤
(1)使用前,必须声明(定义)它。定义要使用的select语句。
(2)一旦声明后,必须打开游标以供使用。用前面的select语句把数据实际检索出来。
(3)对于填有数据的游标,根据需要取出检索各行。
(4)在结束游标使用时,必须关闭游标。
5、创建游标
(1)使用declare语句创建。declare命名游标,并定义相应的select语句,根据需要带where和其他子句。
example:
#案例 CREATE PROCEDURE orders() BEGIN DECLARE youbiaotest CURSOR FOR SELECT ordername FROM workorder; END
存储过程完成后,游标就消失了,因为游标局限于存储过程。
(2)打开和关闭游标
打开:open orders;存储检索出的数据以供浏览和滚动。
关闭:close orders;释放游标所使用的所有内部内存和资源。
(3)隐含关闭:如果没有明确关闭游标,MySQL将会在自动到达end语句时自动关闭它。
6、使用游标数据(重难点)
(1)在一个游标被打开后,fetch语句用来分别访问检索出来数据的每一行。
fetch指定检索什么数据(所需的列),检索出来的数据存储在什么地方。
它还向前移动游标中的内部行指针,使下一行fetch语句检索下一行(不重复读取同一行数据)。
(2)循环检索数据,从第一行到最后一行。
#案例二 DROP PROCEDURE IF EXISTS proorders; DROP TABLE IF EXISTS ordertotals; DELIMITER $$ CREATE PROCEDURE proorders () BEGIN -- declare local variables(声明局部变量) DECLARE done boolean DEFAULT 0 ; DECLARE o INT ; DECLARE t VARCHAR(100) ; -- declare the cursor DECLARE ordernums CURSOR FOR SELECT WORKORDERID,DEPARTMENT FROM wcmworkorder; -- declare continue handler DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1 ; -- CREATE a table to store thr results CREATE TABLE IF NOT EXISTS ordertotals ( order_num INT, total VARCHAR(100) ); -- open the sursor OPEN ordernums ; -- loop through all rows REPEAT -- get order number and dept FETCH ordernums INTO o,t ; -- insert order and total into ordertotals INSERT INTO ordertotals(order_num, total) VALUES(o, t); SELECT t; -- end of loop UNTIL done END REPEAT; -- close the cursor CLOSE ordernums ; END ;$$ DELIMITER ; CALL proorders ();
①MySQL里声明字符变量要带上允许的长度,否则会报错1064。声明的变量要和游标选出来的数据类型相匹配。
②DECLARE ordernums CURSOR FOR SELECT WORKORDERID,DEPARTMENT FROM wcmworkorder; 定义游标
③DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1 ;
这行代码的意思是没有数据返回时,程序继续,同时设置done的值为1。‘02000’也可以用not found 代替。
关于handler异常处理可以参考:Mysql 异常处理--condition和handler
handler命令和实现方法:http://www.jb51.net/article/88732.htm
比较通俗易懂的使用案例:mysql游标的使用
MySQL常用的循环案例:MySQL中的while、repeat、loop循环
MySql中游标的定义与三种使用方式(2)
④fetch用来检索当前行的WORKORDERID,DEPARTMENT到变量o和t中,不对数据做任何处理。
⑤UNTIL done END REPEAT; done为1时结束循环。
⑥OPEN/CLOSE ordernums ;打开或者关闭游标。
⑦CALL proorders ();调用进程。
7、MySQL的错误代码(英文):https://dev.mysql.com/doc/refman/8.0/en/error-handling.html
十四、触发器
1、触发器是MySQL在相应一下任何语句而自动执行的一跳MySQL语句(或位于begin和end之间的一组语句):delete、insert、update。其他MySQL语句不支持触发器。
2、创建触发器,必给的4条信息
(1)唯一的触发器名;
(2)关联的触发器表;
(3)触发器应该相应的活动(delete、insert或者update);
(4)触发器何时执行(处理之前或之后)。
3、保持每个数据库的触发器名唯一:在MySQL5中,触发器名必须在每个表中唯一,但不是在每个数据库中唯一。其他每个数据库的触发器名必须唯一。因此,最好实在数据库中保持触发器的唯一性。
4、创建语句
CREATE TRIGGER ordertatals AFTER INSERT ON products FOR EACH ROW SELECT 'order added' INTO @args;
(书中原本的语句没有带 into @args,会导致触发器创建不成功,报错1064)
(1)用create trigger 语句来创建名称为newproduct的触发器。
(2)触发器可以在操作之前或者操作之后执行,这里是after insert,在插入语句执行之后执行。
(3)FOR EACH ROW表示对每个插入行执行。
(4)表示触发器要执行的内容,把‘order added’赋予到变量args里面。
INSERT INTO ordertotals (order_num,total) VALUES (79,'测试');
SELECT @args;
(5)执行语句insert语句之后输出触发器的内容需要select 变量。
(6)FOR EACH ROW 之后可以是一条SQL语句,也可以是begin和end包含的多条SQL语句。
具体详细解释可以参考博客:MySQL触发器使用详解 以及 我的MYSQL学习心得(十二) 触发器
(学习到这里,让我对MySQL必知必会这本书产生了怀疑…… ̄へ ̄……之后会参照其他书本和网上的内容进行综合比对记录)
再次推博,这个条例比较清晰,而且有总结:mysql触发器trigger 实例详解
(7)仅支持表。每个表每个事件只允许一次触发器。因此每张表只允许有6个触发器(insert、delete、update之前之后。)
(8)如果before触发器失败,MySQL将不执行操作请求,如果有after操作,也不执行。
5、删除触发器:drop trigger。
触发器不能更新或者覆盖,只能先删除,然后在重新创建。
6、使用触发器
(1)insert触发器
drop trigger neworder;
create TRIGGER neworder after insert on ordertotals for each row select NEW.order_num INTO @args;
INSERT INTO ordertotals (order_num,total) VALUES (79,'测试');
SELECT @args;
①在insert触发器的代码内,可以引用一个名为new的虚拟表,用来访问被插入的行。
②在before insert触发器中,new中的值可以被更新(允许更新被插入的值)。
③对于auto_increment 列,new在insert执行之前包含0,在insert执行之后包含新的自动生成值。
备注:before通常用于数据验证和净化(目的是保证插入表中的数据是被需要的数据)。
(2)delete触发器
①在delete触发器代码中,你可以引用一个名为old的虚拟表,访问被删除的行。
②old中的值全部是只读,不能更新。
(3)update触发器
①在update触发器中可以引用一个old的虚拟表访问以前的值,可以引用一个名为new的虚拟表访问更新后的值。
②在before update触发器中,new中的值可能也被更新(允许更改将要用于update更新的值)。
每更新一行是,new中的值(将要用来更新表中的值),都用upper替换。
7、触发器的进一步介绍
(1)创建触发器可能需要特殊的访问权限。
(2)应该用触发器来保证数据的一致性
(3)创建审计跟踪。(把更改记录到另一张表)
(4)触发器不支持call语句,也就是不能从触发器的内部调用存储过程。
十五、管理事务处理
1、事务处理:并非所有的引擎都支持事务处理,myisam不支持明确的事务处理管理,而innodb支持。
2、数据库处理可以用来维护数据库的完整性,它保证成批的MySQL操作要么完全执行,要么完全不执行。
3、(1)事务(transaction):指一组SQL语句。
(2)回退(rollback):指撤销指定SQL语句的过程。
(3)提交(commit):指将未存储的SQL语句结果写入数据库表。
(4)保留点(savepoint):指事务处理中设置的临时占位符(place-holder),你可以对它发布回退(与回退整个事务处理不同)。
4、控制事务处理
(1)标识事务的开始:start transaction
(2)rollback只能在一个事务处理内使用。
(3)MySQL语句都是直接针对数据库表执行和编写的。这就是隐含提交,即提交(写或保存)操作是自动进行的。在事务处理模块中,提交不会隐含进行。
(4)隐含事务关闭:当commit或者rollback语句执行后,事务会自动关闭。
5、使用保留点:复杂的事务有时候需要部分撤回或者部分执行。
为了支持回退部分事务处理,必须能在事务处理块中合适的位置放置占位符,这些占位符成为保留点。
example:savepoint delete1;
回退到保留点时:rollback delete1;
6、保留点越多越好,可以更灵活的处理事务。
7、释放保留点:保留点在事务处理完成后自动释放。也可以明确释放→release savepoint。
8、更改默认的提交行为:默认的MySQL行为是自动提交所有的更改。
为指示MySQL不自动提交行为,需要以下语句:set autocommit=0;
9、标志位连接专用:autocommit标志是针对每个连接而不是服务器。
十六、全球化和本地化:介绍MySQL不同的字符集和语言的基础知识。
1、数据库表被用来存储和检索数据。不同的语言和字符集需要以不同的方式存储和检索。
2、MySQL需要适应不同的字符集和检索方式
(1)字符集:字符和符号的集合。
(2)编码:某个字符集内部成员的表示。
(3)校对:规定字符集如何比较的指令。
3、使用字符集和校对顺序
show character :显示所有可用字符集和以及每个字符集的描述和默认校对。
show collation:查看所支持校对的完整列表。
4、确定数据库使用的字符集和校对
show variables like ‘character%’;
show variables like ‘collation%’;
5、字符集很少是服务器范围的设置。允许对表和列设置。
6、校对对用order by 子句检索出来的数据排序起着重要的作用。
7、select的其他collate子句:除了在order by中使用,还可以在group by、having、聚集函数、别名等中使用。
十七、安全控制
1、MySQL服务器的安全基础:用户对他们访问的数据有适当的访问权,既不能多也不能少。
2、防止无意识错误;给不同的角色创建对应权限的账号,尽可能不使用root。
3、获取所有账号列表:
use MySQL;
select user from user;
4、一般可以借助图形用户界面使用数据库,也可以使用SQL语句创建。
create user ben identified by ‘XXX’;
5、指定散列口令:identified by 指定的口令为纯文本,MySQL将在保存到user表之前对其进行加密。为了作为散列指定口令,使用identified by password。
6、使用grant和insert语句也可以创建账号。
7、rename user:重命名用户账号。
8、删除用户账号(及相关权限):drop user yonghu。
9、设置访问权限:show grants for yonghu;
10、grant的用法:
grant select on shujuku.* to yonghu;
这个grant 是允许用户在数据库shujuku所有的表都可以使用select语句。
11、grant的反操作是revoke,用来撤销指定的权限。
example:revoke select on shujuku.* to yonghu;
12、grant和revoke可控制访问权限的层次:
(1)整个服务器,使用grant all 和revoke all;
(2)整个数据库,on database.*;
(3)特定的表,on database.table;
(4)特定的列;
(5)特定的存储过程;
13、未来授权:使用grant和revoke的时候,用户账号必须存在,但是涉及的对象却不一定。因此可能存在数据库或者表还没有创建,但是权限已经有了。
14、简化多次授权:可通过列出各个权限,并用逗号隔开,将多条grant语句串在一起:
grant select ,insert on database.* to yonghu;
15、更改口令:使用set password 语句。
十八、数据库维护
1、备份数据:MySQL数据库是基于磁盘的文件,普通备份系统和例程就能备份MySQL数据库。但是文件总是处于打开和使用的状态,普通文件副本不一定总是有效。
解决方案:
(1)使用命令MySQLdump转存所有数据库内容到某个外部文件。
(2)可用命令实行程序MySQLhotcopy从一个数据库复制所有数据。
(3)可以使用MySQL的backup table 或者select into outfile转存所有数据到某个文件。
2、首先刷新未写数据:为了保证所有数据被写到磁盘,可能需要在备份数据前使用flush tables语句。
3、进行数据库维护
(1)analyze table:用来检查表键是否正确。
(2)check table:用来针对许多问题对表进行检查。
(3)changed:检查自最后一次检查以来改动过的表。
(4)extended:执行最彻底的检查。
(5)fast:只检查未正常关闭的表。
(6)medium:检查所有被删除的链接并进行键检查。
(7)quick:只进行快速扫描。
(8)repair table:修复相应的表。
(9)optimize table:删除大量表后,收回所用空间,优化表的性能。
4、诊断启动问题
几个重要的mysqld重要选项
(1)--help显示帮助——一个选项列表。
(2)--safe-mode装载减去某些最佳配置的服务器。
(3)--verbose显示全文本消息,与help联合使用。
(4)--version显示版本信息然后退出。
5、日志文件:错误日志、查询日志、二进制日志、缓冲查询日志。
十九、改善性能
1、硬件建议。
2、专属服务器。
3、调整分配。
4、MySQL是多用户多线程的DBMS,可以用show processlist 显示所有进程,kill命令终结某个特定的进程。
5、测试选择最优化语句。
6、explain语句让MySQL解释它将如何执行一跳select语句。
7、检索正确的数据类型。
8、检索合适的数据和数据量。
9、有的操作支持delayed关键字,使用它,将会把控制立刻调回使用程序,一旦有可能就实际执行该操作。
10、导入数据时,应关闭自动提交。
11、必须索引数据库表以改善数据库检索性能。
12、有复杂的or语句时,可以使用union联结。
13、索引根据需要添加。
14、like很慢,最好使用fulltext。
15、数据库是不断变化的实体。
16、最重要的规则,每条规则在特定的条件下会被打破。