本文已收录到1.1K Star数开源学习指南——《大厂面试指北》,若是想要了解更多大厂面试相关的内容及获取《大厂面试指北》离线PDF版,请扫描下方二维码码关注公众号“大厂面试”,谢谢你们了!mysql
《大厂面试指北》最佳阅读地址:git
notfound9.github.io/interviewGu…github
《大厂面试指北》项目地址:面试
获取《大厂面试指北》离线PDF版,请扫描下方二维码关注公众号“大厂面试”算法
《大厂面试指北》项目截图:sql
由于我最近的一些工做内容跟数据分析比较密切,因此须要对SQL使用得比较熟练,因此便阅读了《MySQL 必知必会》这本书,为了检验本身的阅读效果及帮助一些跟我同样须要学习MySQL相关的知识的朋友,因此每阅读一章,我就开始写一章的读书笔记,并在掘金的读书笔记版块发布沸点。一共三十章,所有发布完之后,便汇总成了这篇文章,感兴趣的朋友经过阅读这篇文章,快速得预览这本书,学习MySQL相关的知识。若是你以为这本书对你带来帮助,但愿你能够为我点一个关注,后续也会继续阅读其余的技术书籍,并整理成读书笔记,分享给你们。同时也欢迎你们加我掘金主页的微信,咱们一块儿探讨学习。数据库
本章主要是介绍了一些数据库相关的概念:安全
数据库:保存有组织的数据的容器。bash
表:某种特定类型数据的结构化清单。
模式(schema):关于数据库和表的布局及特性的信息。在MYSQL中,模式与数据库同义。
主键:惟一标识表中每行的这个列称为主键。一个列成为主键必须知足如下条件:
1.惟一性,任意两行都不具备相同的主键值。
2.不为空,每行数据必须具备一个主键值。
DBMS(数据库管理软件)一般分为两类:
1.基于共享文件系统的DBMS。一般用于桌面(例如Microsoft Access和FileMaker)
2.Client-Sever的DBMS。平常见到的MySQL,Oracle,SQL Server数据库都是这种类型的。Client主要负责与用户进行交互,接受用户的指令,而后发出请求给Server,Server负责数据访问和处理,而后将结果返回给Client。
主要介绍了一些MySQL的一些命令
use crashcourse;选择一个名叫crashcourse数据库(在经过命令行链接到数据库时,咱们须要选择一个数据库,而后才能继续操做)
show DATABASES;//展现当前可用的数据库列表
show Tables;//展现当前是选择的是数据库的全部表
show COLUMNS FROM customers;//展现customers表全部的列信息(会包含字段名,类型,是否容许为NULL,键信息,默认值,其余信息),
复制代码
DESCRIBE customers;跟show COLUMNS FROM同义,用于展现表的列信息
SHOW STATUS;展现服务器信息
SHOW CREATE DATABASE crashcourse;
复制代码
展现以前建立crashcourse这个数据库时使用的SQL语句,同理,SHOW CREATE TABLE也能够展现建某张表时使用的SQL语句
SHOW GRANTS FOR 'jeffrey'@'localhost';//展现jeffrey这个帐号的权限 SHOW ERRORS和SHOW WARNINGS,//用来显示服务器错误或警告消息 复制代码
HELP SHOW;当你不了解某个命令时,可使用HELP+这个命令,来得到一些说明信息,了解这个命令的用途,这里HELP SHOW会打印出SHOW命令的用法
这两章主要讲得是查询相关的。
查询时默认的数据顺序:
SELECT prod_name FROM products;
复制代码
若是是不设置任何排序条件,以这种方式来进行查询,返回的数据的顺序是根据它们在底层表中出现的顺序(能够是数据最初添加到表中的顺序,可是若是数据进行过更新或删除,顺序会受到MySQL重用回收存储空间的影响)
SELECT DISTINCT vend_id FROM products;
复制代码
若是想要对让返回的数据不包含重复值,可使用DISTINCT来对列进行修饰
SELECT DISTINCT vend_id,prod_price FROM products;
复制代码
DISTINCT关键字是对全部字段进行修饰的,只有当全部列都相同时,才会进行排除,在上面这个例子中,只有vend_id和prod_price都相同的数据,才会进行排除,也就是能够容许一些vend_id相同,prod_price不一样的数据出现。
SELECT prod_name FROM products LIMIT 5;
复制代码
能够限制返回的数据为5条
SELECT prod_name FROM products LIMIT 4,5;
复制代码
能够限制返回的数据是从第4行开始后面的5条
上面这条查询语句,MySQL 5之后还支持另一种更加容易理解的写法
SELECT prod_name FROM products LIMIT 4 offset 5;
复制代码
使用彻底限定的表名
SELECT products.prod_name FROM crash_course.products;
复制代码
能够限制在某个数据库的某个表中进行查询,上面的例子是限制了,必须在crash_course数据库的products表取prod_name列的数据
这一章主要讲的是ORDER BY对查询结果进行排序,以及使用ASC,DESC控制升序,降序。
SELECT prod_name FROM products ORDER BY product_name;
复制代码
SELECT prod_id, prod_price, prod_name FROM products ORDER BY product_price, product_name;
复制代码
在 ORDER BY 指定多个字段,能够按规定的顺序,按多个列排序,例子中的数据会先根据 product_price 从低到高进行排序,若是 product_price相同,再按 product_name ,就进行比较从A到Z进行排序,以下图所示
默认的排序方向是升序,也就是ASC,有时候须要进行降序排序,例如价格从高到低进行排序,可使用降序DESC
这一章其实主要讲得是WHERE语句对数据进行过滤。
一些常见的WHERE语句的条件判断符,你们已经知道了。 例如:
= 等于
!= 不等于
< 小于
> 大于
<= 小于等于
>= 大于等于
BETWEEN 在指定两个值之间
除了上面这些,有一个不太常见的操做符号
<>,表明不等于,与!= 同义
复制代码
!= 是返回不具有特定值的行,NULL值表明未知,因此不会拿NULL值去跟特定值比较,因此不会具备NULL值的行。若是想要获取具备NULL值的行,必须使用IS NULL 例如:
对下面这个表执行 SELECT * FROM table WHERE value != 100;
id | value |
---|---|
1 | 100 |
2 | NULL |
3 | 200 |
返回的结果:
只会返回value为200的这一行,不会返回值为NULL的行
id | value |
---|---|
3 | 200 |
使用BETWEEN操做符会匹配范围中全部的值,包括指定的开始值和结束值
例如:
这一章主要说的是AND,OR, IN,NOT这四个操做符,
组合AND和OR使用时,由于AND优先级最高计算时会优先处理AND操做符,会将AND两边的条件进行提取,因此上面这个SQL语句其实会等价于
SELECT prod_name, prod_price FROM products WHERE vend_id = 1002 OR (vend_id = 1003 AND prod_price >= 10);
复制代码
可能会与咱们想要的结果会有必定差距,咱们是想要
SELECT prod_name, prod_price FROM products WHERE vend_id = 1002 OR (vend_id = 1003 AND prod_price >= 10);
复制代码
可能会与咱们想要的结果会有必定差距,咱们是想要vend_id为1002或1002,且prod_price大于10的数据,因此在平常使用中,最好使用()明确地分组相应的操做符,而不是依赖操做符的优先级,像下面这样:
SELECT prod_name, prod_price FROM products WHERE (vend_id = 1002 OR vend_id = 1003) AND prod_price >= 10;
复制代码
在指定条件范围进行匹配时,IN和OR都能知足需求,可是IN有一些优势:
1.IN操做符语法更加简洁直观,容易管理
2.IN操做符执行更快。
3.IN的最大优势是能够包含其余SELECT语句,从而能够动态地简历WHERE语句,第14章会对此进行详细介绍。
其余DBMS容许使用NOT对各类条件取反,但在MySQL中,只支持使用NOT对IN、BETWEEN和EXISTS子句取反。
这一章主要是介绍了LIKE操做符,以及%,_ 这两个通配符。
LIKE主要是配合通配符一块儿使用的,LIKE 操做符用于在 WHERE 子句中搜索列中的指定模式。
%表明搜索模式中给定位置的0个、1个或多个字符。
可能会干扰通配符匹配。例如,在保存词 anvil时,若是它后面有一个或多个空格,则子句WHERE prod_name LIKE '%anvil'将不会匹配它们,由于在最后的l 后有多余的字符。解决这个问题的一个简单的办法是在搜索模式最后附加一个%。一个更好的办法是使用函数(第11章将会 介绍)去掉首尾空格。 注意NULL 虽然彷佛%通配符能够匹配任何东西,但有一个例 外,即NULL。即便是WHERE prod_name LIKE '%'也不能匹配 用值NULL做为产品名的行。 下划线(_)通配符 _通配符与%通配符相似,只不过只能匹配单个字符,不能匹配0个字符,也不能匹配多个字符
1.在能使用其余操做符的请款下,尽可能不要使用通配符,由于它的搜索事件要比其余操做符的长
2.尽可能不要把通配符用在搜索模式的开始处。放在搜索模式的开始处,搜索起来是最慢的。
3.仔细检查通配符的位置。若是放错地方,可能不会返回想要的数据。
这一章主要讲得是正则相关的知识,我我的认为把正则当成一门单独的技术进行学习会比较好,因此建议能够专门去学习
某些场景下,存储在的表中的数据不是咱们所须要的,咱们须要对它进行转换、计算或格式化过,这就是计算字段的用途。
多数DBMS使用+或||来实现拼接, MySQL则使用Concat()函数来对字段进行拼接。Concat()能够将多个字符串拼接成一个,以下图所示:
Trim()函数 :去除字符串左右两边的空格 LTrim()函数 :去除字符串左边的空格 RTrim()函数 :去除字符串右边的空格 下面是使用RTrim()函数的例子
咱们使用Concat()函数拼接出来的字段是没有名字的,可使用AS关键字给它赋予一个名字,固然当已有的字段包含不符合规定的字符时,也能够AS关键字给一个已有字段起别名。
除了使用Concat()函数获得一个计算字符,也可使用+,-,,/计算获得一个字段。如图所示:
除了使用SQL语句对数据进行处理,还可使用一些函数对数据进行处理,须要注意的是,函数没有SQL的可移植性那么强。
使用案例: 这是使用Upper()函数将文本处理成大写的案例
上面这些常见函数你们可能都可以理解,只有Soundex()不太常见,SOUNDEX是一个将任何文 本串转换为描述其语音表示的字母数字模式的算法。
在平常开发中,咱们除了得到检索获得的数据,还可使用聚合函数对数据汇总,获得处理后的结果。
AVG()是计算特定列的平均值,会忽略掉值为NULL的列。
两种用法: 1.使用COUNT(*)对表中行的数目进行计数,无论表列中包含的是空值(NULL)仍是非空值。 2.使用COUNT(column)对特定列中具备值的行进行计数,会忽略 NULL值。
这一章主要讲了若是使用GROUP BY 对数据进行分组。
若是要对分组进行过滤,咱们可使用WHERE语句对表中数据进行过滤后,而后使用GROUP BY进行分组,也能够在使用GROUP BY进行分组后,再使用HAVING语句过滤掉一些分组。 例如:
id | value |
---|---|
1 | 100 |
2 | 150 |
3 | 200 |
3 | 500 |
对于上面这个表的数据,若是咱们想要过滤掉id为3的分组,那么能够写成使用WHERE语句的方式:
SELECT id,COUNT(*) FROM table WHERE id != 3 GROUP BY id;
复制代码
也能够写成使用HAVING语句的方式:
SELECT id,COUNT(*) FROM table GROUP BY id HAVING id !=3;
复制代码
固然在过滤分组这方面,HAVING要比WHERE更增强大,好比咱们想要对数据分组,而且获得数量大于2的组,那么WHERE就没法实现,只能用HAVING语句。以下:
使用GROUP BY在对数据进行分组后,输出的组的顺序一般是按从小到到大,从A到Z升序输出的,可是SQL规范并无对此进行明确要求,因此有可能不是顺序的,可使用ORDER BY来对分组进行升序或者降序排序。
在使用这些语句时,它们的前后顺序应该要按下面的表中顺序来写
有时候一条SELECT语句没法知足咱们的需求,咱们能够把一条SELECT语句的结果用于另一条SELECT语句的WHERE子句,来实现复杂查询。
例如:咱们想要获取订购物品TNT2的全部客户的名字和联系方式: 能够按照下图中的复杂查询实现:
(1) 查询包含物品TNT2的全部订单的编号。 (2) 根据订单编号查询全部客户的ID。 (3) 根据客户的ID查询名字和联系方式。
在WHERE子句中使用子查询可以编写出功能很强而且很灵活的 SQL语句。对于能嵌套的子查询的数目没有限制,不过在实际使用时因为 性能的限制,不能嵌套太多的子查询。
须要的注意的地方:
1.能嵌套的子查询的数目没有限制,不过在实际使用时因为 性能的限制,不能嵌套太多的子查询。
2.列必须匹配,在WHERE子句中使用子查询,应该保证SELECT语句具备与WHERE子句中相同数目的列。一般,子查询将返回单个列而且与单个列匹配,但若是须要也可使用多个列。
3.子查询通常与IN操做符结合使用,但也能够用于测试等于(=)、 不等于(<>)等。
例如:咱们想要在获取顾客的信息的同时,获取客户的订单数,可使用子查询来实现,以下图所示:
有时候针对单表的查询没法知足咱们的需求,咱们须要链接多个表,返回一组输出。链接并非物理实体,只是在查询时创建。
在进行链接查询时,若是不指定任何WHERE 条件,那么返回的结果会是笛卡尔积,会拿第一个表中的行数与第二个表中的全部行进行配对,最终总行数会是第一个表的行数乘以第二个表中的行数。
若是指定了WHERE条件,获得的结果会是根据条件对笛卡尔积的结果进行筛选过滤后的结果。例如在这个例子中,指定了products表的vend_id与vendors表的vend_id相等做为筛选条件,这样,链接的结果就是拿vendors表的vend_id去products表中找相匹配的数据。
上面的这种链接实际上是等值链接,能够用链接的语法来写,能够更加明确链接类型
一条SELECT语句能够链接的表的数量没有限制,能够链接多个表,进行查询
以前经过子查询嵌套来完成多表查询,如今可使用链接来实现
本章将讲解外链接,以及如何对被联结的表使用表别名和汇集函数。
除了能够对列,计算字段起别名之外,还能够对表起别名。主要有如下好处:
1.缩短SQL语句(有些表名太长,能够起短的别名)
2.容许在单条SELECT语句中屡次使用相同的表(对表进行自链接查询时会须要屡次使用相同的表,在下面有相应的例子说明)
除了上一章讲到的内部链接(等值链接)觉得,还有自链接,天然链接,外部链接三种链接:
自链接指的是一张表对自身进行链接,进行信息查询。 例如: 某物品(其ID为DTNTR)存在问题,所以想知道生产该物 品的供应商生产的其余物品是否也存在这些问题。此查询要求首先找到 生产ID为DTNTR的物品的供应商,而后找出这个供应商生产的其余物品。 可使用自链接的实现:
此查询中须要的两个表其实是相同的表,所以products表在 FROM子句中出现了两次。虽然这是彻底合法的,但对products 的引用具备二义性,因此使用表别名避免歧义。 固然解决上面的这个查询需求也可使用子查询来实现,以下图所示:
内部链接会将一个表中的行与另外一个表中的行想关联,有时候也须要包含不知足关联条件的那些行,这就是外链接。 例如:
使用带汇集函数的链接 汇集函数也能够和链接结合起来使用。
1.注意所使用的联结类型。通常咱们使用内部联结,但使用外部联 结也是有效的。
2.保证使用正确的联结条件,不然将返回不正确的数据。
3.应该老是提供联结条件,不然会得出笛卡儿积。
4.在一个联结中能够包含多个表,甚至对于每一个联结能够采用不一样的联结类型。虽然这样作是合法的,通常也颇有用,但应该在一块儿测试它们前,分别测试每一个联结。这将使故障排除更为简单。
在 MySQL 中,能够执行多条查询语句,而后对多个结果集,使用UNION语句合并成单个查询结果集返回。主要有如下两种应用场景: 1.在单个查询中从不一样的表返回相似结构的数据。 2.对单个表执行多个查询,将结果集合并成一个结果集。
例如咱们须要价格小于等于5的全部物品的一个列表,并且 还想包括供应商1001和1002生产的全部物品(不考虑价格),
这条语句由前面的两条SELECT语句组成,语句中用UNION关键 字分隔。UNION指示MySQL执行两条SELECT语句,并把输出组 合成单个查询结果集,固然这个需求也可使用多条WHERE语句来实现。
1.UNION必须由两条或两条以上的SELECT语句组成,语句之间用关 键字UNION分隔(所以,若是组合4条SELECT语句,将要使用3个 UNION关键字)。
2.UNION中的每一个查询必须包含相同的列、表达式或汇集函数(不过 3.列数据类型必须兼容:类型没必要彻底相同,但必须是DBMS能够 隐含地转换的类型(例如,不一样的数值类型或不一样的日期类型)。 若是遵照了这些基本规则或限制,则能够将并用于任何数据检索任务。
4.在用UNION组合查询时,若是须要对结果进行排序,只能使用一条ORDER BY子句,它必须出如今最后一条SELECT语句以后。对 于结果集,不存在用一种方式排序一部分,而又用另外一种方式排序另外一 部分的状况,所以不容许使用多条ORDER BY子句。
5.UNION从查询结果集中自动去除了重复的行(换句话说,它的行为与 单条SELECT语句中使用多个WHERE子句条件同样)。由于供应商1002生产 的一种物品的价格也低于5,因此两条SELECT语句都返回该行。在使用 UNION时,重复的行被自动取消。这是UNION的默认行为,可是若是容许重复,可使用UNION ALL而不是UNION。以下图所示:
当咱们须要对文本进行匹配,可使用LIKE+通配符,或正则表达式的方式来实现,可是这样会存在不少限制:
1.性能不高——通配符和正则表达式匹配一般要求MySQL尝试匹配表中全部行(并且这些搜索极少使用表索引)。所以,因为被搜索行数不断增长,这些搜索可能很是耗时。
2.不太灵活——使用通配符和正则表达式匹配,很难(并且并不老是能)明确地控制匹配什么和不匹配什么。例如,指定一个词必须匹配,一个词必须不匹配,而一个词仅在第一个词确实匹配的状况下才能够匹配或者才能够不匹配。
3.没法智能化——虽然基于通配符和正则表达式的搜索提供了很是灵活的搜索,但它们都不能提供一种智能化的选择结果的方法。 例如,一个特殊词的搜索将会返回包含该词的全部行,而不区分包含单个匹配的行和包含多个匹配的行(按照多是更好的匹配 来排列它们)。相似,一个特殊词的搜索将不会找出不包含该词但包含其余相关词的行。因此就有了全文搜索,为了进行全文本搜索,必须索引被搜索的列,并且要随着数据的改 变不断地从新索引。在对表列进行适当设计后,MySQL会自动进行全部 的索引和从新索引。在索引以后,SELECT可与Match()和Against()一块儿使用以实际执行 搜索。
在建表时或者建表之后使用FULLTEXT语句指定全文搜索的列,MySQL根据子句FULLTEXT(note_text)的指示对它进行索引,在以后该列增长、更新或删除行时, 索引随之自动更新 以下图所示:
若是正在导入数据到一个新表, 此时不该该启用FULLTEXT索引。应该首先导入全部数据,而后再修改表,定义FULLTEXT,这样花费的时间会更少。
在索引以后,使用两个函数Match()和Against()执行全文本搜索, Match() 指定被搜索的列 Against() 指定要使用的搜索表达式 以下图所示:SELECT语句检索单个列note_text,将包含rabbit的行进行返回。(全文搜索默认不区分大小写,除非使用BINARY语句进行修饰)
全文搜索还可使用Rank对结果进行排序,Match()和Against() 用来创建一个计算列(别名为rank),此列包含全文本搜索计算出的等级 值。等级由MySQL根据行中词的数目、惟一词的数目、整个索引中词的 总数以及包含该词的行的数目计算出来。不包含搜索词的行等级为0(所以不被前一例子中的WHERE子句选择)。确实包含搜索词的两个行每行都有一个等级值,文本中词靠前的行的等级值比词靠后的行的等级值高。以下图所示:
若是指定多个搜索项,则包含多数匹配词的 那些行将具备比包含较少词(或仅有一个匹配)的那些行高的 等级值。
查询扩展用来设法放宽所返回的全文本搜索结果的范围,它能够先进行一个基本的全文本搜索,找出与搜索条件匹配的全部行。其次,MySQL检查这些匹配行并选择全部有用的词,再其次,MySQL再次进行全文本搜索,此次不只使用原来的条件, 并且还使用全部有用的词。以下图所示;
MySQL支持全文本搜索的另一种形式,称为布尔方式(boolean mode)。能够指定要匹配的词,要排斥的词,排列提示(指定某些词比其余词更重要,更重要的词等级更高),表达式分组等。即便没有定义 FULLTEXT索引,也可使用它。但这是一种很是缓慢的操做。 例如: 在下图里面的查询中,会匹配词heavy,但-rope明确地 分析指示MySQL排除包含rope(任何以rope开始的词,包括 ropes)的行。
除了布尔操做符-和*,-排除一个词,而* 是截断操做符(可想象为用于词尾的一个通配符)。还有如下全文本布尔操做符:
下面是一些全文本布尔操做符使用案例:
全文本搜索的使用说明
1.在索引全文本数据时,短词被忽略且从索引中排除。短词定义为 那些具备3个或3个如下字符的词(若是须要,这个数目能够更改)。
2.MySQL带有一个内建的非用词(stopword)列表,这些词在索引全文本数据时老是被忽略。若是须要,能够覆盖这个列表(请参阅MySQL文档以了解如何完成此工做)。
3.许多词出现的频率很高,搜索它们没有用处(返回太多的结果)。所以,MySQL规定了一条50%规则,若是一个词出如今50%以上的行中,则将它做为一个非用词忽略。50%规则不用于IN BOOLEAN MODE。
4.若是表中的行数少于3行,则全文本搜索不返回结果(由于每一个词或者不出现,或者至少出如今50%的行中)。
5.忽略词中的单引号。例如,don't索引为dont。
6.不具备词分隔符(包括日语和汉语)的语言不能恰当地返回全文 本搜索结果。
7.如前所述,仅在MyISAM数据库引擎中支持全文本搜索。
8.没有邻近操做符,邻近搜索是许多全文本搜索支持的一个特 性,它能搜索相邻的词(在相同的句子中、相同的段落中或者 在特定数目的词的部分中,等等。MySQL全文本搜索如今还不支持邻近操做符。
使用INSERT语句插入数据,你们都很熟悉。 例如向 Customers 表插入一条name为tom,age为29的数据 通常有如下两种方式:
INSERT INTO Customers VALUES("tom", "29"); INSERT INTO Customers(name, age) VALUES("tom", "29"); 复制代码
通常推荐第二张方式,由于第一种方式的数据顺序必须与列在表中的数据保持一致,容易写错,其次是当表结构发生改变时,第一种方式须要变动数据顺序,第二种方式不须要。
INSERT通常用来给表插入一个指定列值的行。可是,INSERT还存在 另外一种形式,能够利用它将一条SELECT语句的结果插入表中。以下图所示,这个例子使用INSERT SELECT从custnew表中将全部数据导入customers表
使用UPDATE语句更新数据,你们都很熟练了,通常UPDATE语句组成部分以下:
UPDATE 表名
SET 列名 = 新值
WHERE 过滤条件;
复制代码
以下图所示:
1.在使用UPDATE语句时,不要省略WHERE子句 ,不然就会更新表中全部行。
2.IGNORE关键字,若是用UPDATE语句更新多行,而且在更新这些行中的一行或多行时出一个现错误,则整个UPDATE操做被取消 (错误发生前更新的全部行被恢复到它们原来的值)。为即便是发生错误,也继续进行更新,可以使用IGNORE关键字,以下所示: UPDATE IGNORE customers...
使用DELETE语句更新数据,你们也都很熟练了,通常DELETE语句组成部分以下:
DELETE FROM 表名 WHERE 过滤条件;
以下图所示:
1.在使用DELETE语句时,不要省略DELETE子句 ,不然会删除表中全部行。
2.DELETE语句从表中删除行,甚至是删除表中全部行。可是,DELETE不删除表自己。
3.若是想从表中删除全部行,不要使用DELETE。 可以使用TRUNCATE TABLE语句,它完成相同的工做,但速度更快,由于TRUNCATE实际是删除原来的表并从新建立一个表,而不是逐行删除表中的数据
更新和删除的指导原则
1.除非确实打算更新和删除每一行,不然绝对不要使用不带WHERE 子句的UPDATE或DELETE语句。
2.保证每一个表都有主键(若是忘记这个内容,请参阅第15章),尽量 像WHERE子句那样使用它(能够指定各主键、多个值或值的范围)。
3.在对UPDATE或DELETE语句使用WHERE子句前,应该先用SELECT进行测试,保证它过滤的是正确的记录,以防编写的WHERE子句不正确。
4.使用强制实施引用完整性的数据库(关于这个内容,请参阅第15 章),这样MySQL将不容许删除具备与其余表相关联的数据的行。
5.MySQL没有撤销(undo)按钮。应该很是当心地使用UPDATE和DELETE,不然你会发现本身更新或删除了错误的数据。
使用CREATE语句来建立一个表,你们都很熟悉了,以下图所示
须要注意的有如下几点:
1.在建表时,每一列要么是可为NULL列,要么是NOT NULL列,若是不指定,默认为可为NULL列。
2.主键必须保证惟一,不能为NULL。若是使用一个列做为主键,值必须惟一,若是使用多个列做为主键,那么多个列组合的值必须惟一。
3.MySQL有一个具体管理和处理数据的内部引擎,在执行SQL语句时,可使用ENGINE语句指定引擎,若是省略ENGINE=语句,则使用默认引擎(极可能是MyISAM),如下为MySQL常见的几个引擎: InnoDB
是一个可 靠的事 务 处 理 引 擎 ( 参 见 第 26 章 ), 它 不 支 持 全 文 本搜索;
MEMORY
在功能等同于MyISAM,但因为数据存储在内存(不是磁盘) 中,速度很快,因此特别适合于临时表;
MyISAM
是一个性能极高的引擎,它支持全文本搜索(参见第18章), 但不支持事务处理。
在表创建之后,若是须要对表结构进行修改,咱们可使用ALTER TABLE语句对表进行修改。例如:
复杂的表结构更改通常须要手动删除过程,它涉及如下步骤:
1.用新的列布局建立一个新表。
2.使用INSERT SELECT语句从旧表复制数据到新表。若是有必要,可以使用转换函数和计算字段。
3.检验包含所需数据的新表。
4.重命名旧表(若是肯定,能够删除它)。
5.用旧表原来的名字重命名新表。
6.根据须要,从新建立触发器、存储过程、索引和外键。
删除表(删除整个表而不是其内容)很是简单,使用DROP TABLE语,例如: 删除customers2表
DROP TABLE customers2;
复制代码
使用RENAME TABLE语句能够重命名一个表。 例如: 将表customers2名字改成customers
RENAME TABLE customers2 to customers;
复制代码
视图为虚拟的表。它们包含的不是数据而是根据须要检索数据的查 询。视图提供了一种MySQL的SELECT语句层次的封装,可用来简化数据 处理以及从新格式化基础数据或保护基础数据。
1.重用SQL语句。
2.简化复杂的SQL操做。在编写查询后,能够方便地重用它而没必要 知道它的基本查询细节。
3.使用表的组成部分而不是整个表。
4.保护数据。能够给用户授予表的特定部分的访问权限而不是整个表的访问权限。
5.更改数据格式和表示。视图可返回与底层表的表示和格式不一样的数据。
1.与表同样,视图必须惟一命名(不能给视图取与别的视图或表相 同的名字)。
2.对于能够建立的视图数目没有限制。
3.为了建立视图,必须具备足够的访问权限。这些限制一般由数据库管理人员授予。
4.视图能够嵌套,便可以利用从其余视图中检索数据的查询来构造一个视图。
5.ORDER BY能够用在视图中,但若是从该视图检索数据SELECT中也含有ORDER BY,那么该视图中的ORDER BY将被覆盖。
6.视图不能索引,也不能有关联的触发器或默认值。
7.视图能够和表一块儿使用。例如,编写一条联结表和视图的SELECT语句。
1.视图用CREATE VIEW语句来建立。
2.使用SHOW CREATE VIEW viewname;来查看建立视图的语句。
3.用DROP删除视图,其语法为DROP VIEW viewname;。
4.更新视图时,能够先用DROP再用CREATE,也能够直接用CREATE OR REPLACE VIEW。若是要更新的视图不存在,则第2条更新语句会建立一个视图;若是要更新的视图存在,则第2条更新语句会替换原有视图。
咱们上面的例子中视图的做用实际上是简化复杂SQL的使用,其实视图还有其余的做用,例如:
视图是可更新的(也就是能够对它们使用INSERT、UPDATE和DELETE)。更新一个视图将更新其基表(能够回忆一下,视图自己没有数据)。若是你对视图增长或删除行,其实是对其基表增长或删除行。可是当视图定义中有如下操做时,则不能进行视图的更新:
1.分组(使用GROUP BY和HAVING); 联结;
2.子查询;
3.并;
4.汇集函数(Min()、Count()、Sum()等);
5.DISTINCT;
6.导出(计算)列。
存储过程,就是能够一条或多条MySQL语句的组合起来,而且能够加入一些业务逻辑。
简单的示例: 使用CREATE PROCEDURE语句建立一个存储过程,对一个SELECT语句进行封装,以后可使用CALL语句来执行这个存储过程。
可使用DROP PROCEDURE 语句来删除一个存储过程,例如: 删除名为productpricing的存储过程
DROP PROCEDURE productpricing;
复制代码
在建立存储过程时,可使用IN语句来存储传入参数,OUT语句来存储返回结果。 在下面这个例子中,20005是传入参数,@total是返回结果。传入参数和返回结果也能够定义多个。
在建立存储过程当中,也可使用IF,THEN,END IF语句来设置判断条件,这是存储过程与简单的语句封装最大的区别。
例如:
可使用 SHOW CREATE PROCEDURE 语句显示用来建立一个存储过程的 CREATE 语句也可使用 SHOW PROCEDURE STATUS 列出全部存储过程。为限制其输出,可以使用LIKE指定一个过滤模式,例如:SHOW PROCEDURE STATUS LIKE 'ordertotal';
游标(cursor)是一个存储在MySQL服务器上的数据库查询, 它不是一条SELECT语句,而是被该语句检索出来的结果集。在存储了游 标以后,应用程序能够根据须要滚动或浏览结果集中的数据。
定义了一个名为ordernumbers的游标
打开名为ordernumbers的游标
OPEN ordernumbers;
复制代码
关闭名为ordernumbers的游标
CLOSE ordernumbers;
复制代码
若是不明确关闭游标,MySQL将会在到达END语句时自动关闭它。
可使用触发器是在MySQL响应 INSERT UPDATE DELETE 语句先后自动执行一条MySQL语句。
建立触发器语句的格式通常是 CREATE TRIGGER 触发器名称 触发时机 触发操做 FOR EACH ROW 执行操做; 例如:
CREATE TRIGGER newproduct AFTER INSERT FOR EACH ROW SELECT 'Product added'; 复制代码
CREATE TRIGGER用来建立名为newproduct的新触发器。触发器 可在一个操做发生以前或以后执行,这里给出了AFTER INSERT, 因此此触发器将在INSERT语句成功执行后执行。这个触发器还指定FOR EACH ROW,所以代码对每一个插入行执行。在这个例子中,文本Product added将对每一个插入的行显示一次。
DROP TRIGGER newproduct;删除名为newproduct的触发器
复制代码
在INSERT触发器代码内,可引用一个名为NEW的虚拟表,访问被 插入的行;
在BEFORE INSERT触发器中,NEW中的值也能够被更新(容许更改 被插入的值);
对于AUTO_INCREMENT列,NEW在INSERT执行以前列的值会是0,在INSERT 执行以后包含新的自动生成值。
DELETE触发器在DELETE语句执行以前或以后执行,在DELETE触发器代码内,你能够引用一个名为OLD的虚拟表,访问被删除的行。OLD中的值全都是只读的,不能更新。
UPDATE触发器在UPDATE语句执行以前或以后执行。在UPDATE触发器代码中,你能够引用一个名为OLD的虚拟表访问 之前(UPDATE语句前)的值,引用一个名为NEW的虚拟表访问新 更新的值。在BEFORE UPDATE触发器中,NEW中的值可能也被更新(容许更改 将要用于UPDATE语句中的值)。OLD中的值全都是只读的,不能更新。
1.只有表才支持触发器,视图不支持(临时表也不 支持)。
2.若是BEFORE触发器失败,则MySQL将不执行请求的操做。此外,若是BEFORE触发器或语句自己失败,MySQL 将不执行AFTER触发器(若是有的话)。
3.与其余DBMS相比,MySQL 5中支持的触发器至关初级。将来的MySQL版本中有一些改进和加强触发器支持的计划。
4.建立触发器可能须要特殊的安全访问权限,可是,触发器的执行是自动的。若是INSERT、UPDATE或DELETE语句可以执行,则相关 的触发器也能执行。
5.应该用触发器来保证数据的一致性(大小写、格式等)。在触发器中执行这种类型的处理的优势是它老是进行这种处理,并且是透 明地进行,与客户机应用无关。
6.触发器的一种很是有意义的使用是建立审计跟踪。使用触发器, 把更改(若是须要,甚至还有以前和以后的状态)记录到另外一个 表很是容易。
7.遗憾的是,MySQL触发器中不支持CALL语句。这表示不能从触发 器内调用存储过程。所需的存储过程代码须要复制到触发器内。
事务处理能够用来维护数据库的完整性,它保证一组SQL语句要么彻底执行,要么彻底不执行。利用事务处理,能够保证一组操做不会中途中止,它们 或者做为总体执行,或者彻底不执行(除非明确指示)。若是没有错误发 生,整组语句提交给(写到)数据库表。若是发生错误,则进行回退(撤 销)以恢复数据库到某个已知且安全的状态。 事务(transaction)指一组SQL语句; 回退(rollback)指撤销指定SQL语句的过程; 提交(commit)指将未存储的SQL语句结果写入数据库表; 保留点(savepoint)指事务处理中设置的临时占位符(place- holder),你能够对它发布回退(与回退整个事务处理不一样)。
事务开始 START TRANSACTION
复制代码
MySQL的ROLLBACK命令用来回退(撤销)MySQL语句。例如:
通常的MySQL语句都是直接针对数据库表执行和编写的。这就是所谓的隐含提交(implicit commit),即提交(写或保存)操做是自动进行的。可是,在事务处理块中,提交不会隐含地进行。为进行明确的提交, 使用COMMIT语句。
简单的ROLLBACK和COMMIT语句就能够写入或撤销整个事务处理。但 是,只是对简单的事务处理才能这样作,更复杂的事务处理可能须要部 分提交或回退。为了支持回退部分事务处理,必须能在事务处理块中合适的位置放 置占位符。这样,若是须要回退,能够回退到某个占位符。
SAVEPOINT delete1;建立一个名称为delete1的占位符
ROLLBACK TO delete1;回退到delete1的占位符
复制代码
保留点在事务处理完成(执行一条ROLLBACK或 COMMIT)后自动释放。自MySQL 5以来,也能够用RELEASE SAVEPOINT明确地释放保留点。
默认的MySQL行为是自动提交全部更改。换句话说,任何 时候你执行一条MySQL语句,该语句实际上都是针对表执行的,并且所作 的更改当即生效。为指示MySQL不自动提交更改,可使用
SET autocommit=0;
复制代码
autocommit标志决定是否自动提交更改,无论有没有COMMIT 语句。设置autocommit为0(假)指示MySQL不自动提交更改 (直到autocommit被设置为真为止)。
数据库表被用来存储和检索数据。不一样的语言和字符集须要以不一样 的方式存储和检索。所以,MySQL须要适应不一样的字符集(不一样的字母 和字符),适应不一样的排序和检索数据的方法。
show CHARACTER SET;
复制代码
能够展现可用的字符集,MySQL 默认字符集是latin1,通常咱们经常使用的就是utf8
show COLLATION;
复制代码
能够展现所支持校对以及它们适用的字符集的完整列表,有的字符集具备不止一种校对。
一般系统管理在安装时定义一个默认的字符集和校对。此外,也可 以在建立数据库时,指定默认的字符集和校对。和校对,可使用如下语句进行查看:
show VARIABLES like 'character%';查看字符集相关的配置 show VARIABLES like 'collation%';查看校对相关的配置 复制代码
1.若是指定CHARACTER SET和COLLATE二者,则使用这些值。
2.若是只指定CHARACTER SET,则使用此字符集及其默认的校对(如SHOW CHARACTER SET的结果中所示)。
3.若是既不指定CHARACTER SET,也不指定COLLATE,则使用数据库默认。
MySQL用户帐号和信息存储在名为mysql的MySQL数据库中。 得到全部用户帐号列表
CREATE USER ben IDENTIFIED BY 'passwOrd'; CREATE USER建立一个新用户帐号。在建立用户帐号时不必定须要密码,不过这个例子用IDENTIFIED BY 'passwOrd'给出了一个密码。
RENAME USER ben TO bforta;
复制代码
DROP USER bforta;
复制代码
为看到赋予用户帐号的权限,使用SHOW GRANTS FOR,以下图所示:
GRANT语句的通常格式是 GRANT 权限 ON 范围 TO 用户; 例如:
GRANT SELECT ON crashhouse.* TO bforta;
复制代码
GRANT容许用户在crashcourse.*(crashcourse数据库的所 有表)上使用SELECT语句。
SHOW GRANTS能够用来显示bforta用户的权限
GRANT的反操做为REVOKE,用它来撤销特定的权限。
REVOKE SELECT ON crashhouse.* FROM bforta;
复制代码
这条REVOKE语句取消刚赋予用户bforta的SELECT访问权限。被 撤销的访问权限必须存在,不然会出错。
GRANT和REVOKE可在几个层次上控制访问权限:
1.整个服务器,使用GRANT ALL和REVOKE ALL;
2.整个数据库,使用ON database.*;
3.特定的表,使用ON database.table;
4.特定的列;
5.特定的存储过程。
下面是能够授予或撤销的每一个权限:
在使用GRANT和REVOKE时,用户帐号必须存在, 但对所涉及的对象没有这个要求。这容许管理员在建立数据库 和表以前设计和实现安全措施。这样作的反作用是,当某个数据库或表被删除时(用DROP语 句),相关的访问权限仍然存在。并且,若是未来从新建立该 数据库或表,这些权限仍然起做用。
更改特定用户的密码
SET PASSWORD FOR bforta = Password('123456'); 复制代码
更改当前用户的密码
SET PASSWORD = Password('123456'); 复制代码
备份数据通常有如下几种方案:
1.使用命令行实用程序 mysqldump 转储全部数据库内容到某个外部 文件。在进行常规备份前这个实用程序应该正常运行,以便能正 确地备份转储文件。
2.可用命令行实用程序 mysqlhotcopy 从一个数据库复制全部数据 (并不是全部数据库引擎都支持这个实用程序)。
3.可使用 MySQL 的 BACKUP TABLE 或 SELECT INTO OUTFILE 转储全部数据到某个外部文件。这两条语句都接受将要建立的系统文件名,此系统文件必须不存在,不然会出错。数据能够用 RESTORE TABLE 来复原。
ANALYZE TABLE 用来检查表键是否正确,返回的状态信息以下:
CHECK TABLE 用来针对许多问题对表进行检查。在MyISAM表上还对索引进行检查。 CHECK TABLE支持一系列的检查选项(仅用于MyISAM表) :
CHANGED 检查自最后一次检查以来改动过的表
EXTENDED 执行最完全的检查
FAST 只检查未正常关闭的表
MEDIUM 检查全部被删 除的连接并进行键检验
QUICK 只进行快速扫描 以下所示,CHECK TABLE发现和修复问题:
若是MyISAM表访问产生不正确和不一致的结果,可能须要用REPAIR TABLE来修复相应的表。这条语句不该该常用,若是须要常用,可能会有更大的问题要解决。 若是从一个表中删除大量数据,应该使用OPTIMIZE TABLE来收回所用的空间,从而优化表的性能。
服务器启动问题一般在对MySQL配置或服务器自己进行更改时出现。MySQL在这个问题发生时报告错误,但因为多数MySQL服务器是做为系统进程或服务自动启动的,这些消息可能看不到。 在排除系统启动问题时,首先应该尽可能用手动启动服务器。MySQL 服务器自身经过在命令行上执行mysqld启动。下面是几个重要的mysqld命令行选项:
--help 显示帮助
--safe-mode 装载减去某些最佳配置的服务器
--verbose 显示全文本消息(为得到更详细的帮助消息与--help联合使用)
--version 显示版本信息而后退出
查看日志文件
MySQL维护管理员依赖的一系列日志文件。主要的日志文件有如下几种。
错误日志
它包含启动和关闭问题以及任意关键错误的细节。此日志一般名为hostname.err,位于data目录中。此日志名可用 --log-error命令行选项更改。
查询日志
它记录全部MySQL活动,在诊断问题时很是有用。此日志文件可能会很快地变得很是大,所以不该该长期使用它。此 日志一般名为hostname.log,位于data目录中。此名字能够用 --log命令行选项更改。
二进制日志
它记录更新过数据(或者可能更新过数据)的全部语句。此日志一般名为hostname-bin,位于data目录内。此名字 能够用--log-bin命令行选项更改。注意,这个日志文件是MySQL 5 中添加的,之前的MySQL版本中使用的是更新日志。
缓慢查询日志
顾名思义,此日志记录执行缓慢的任何查询。这 个日志在肯定数据库何处须要优化颇有用。此日志一般名为 hostname-slow.log,位于data目录中。此名字能够用 --log-slow-queries命令行选项更改。 在使用日志时,可用FLUSH LOGS语句来刷新和从新开始全部日志文件。
1.首先,MySQL(与全部DBMS同样)具备特定的硬件建议。在学习和研究MySQL时,使用任何旧的计算机做为服务器均可以。但对用于生产的服务器来讲,应该坚持遵循这些硬件建议。
2.通常来讲,关键的生产DBMS应该运行在本身的专用服务器上。
3.MySQL是用一系列的默认设置预先配置的,从这些设置开始一般是很好的。但过一段时间后你可能须要调整内存分配、缓冲区大 小等。(为查看当前设置,可以使用SHOW VARIABLES;和SHOW STATUS;)
4.MySQL一个多用户多线程的DBMS,换言之,它常常同时执行多个任务。若是这些任务中的某一个执行缓慢,则全部请求都会执 行缓慢。若是你遇到显著的性能不良,可以使用SHOW PROCESSLIST 显示全部活动进程(以及它们的线程ID和执行时间)。你还能够用KILL命令终结某个特定的进程(使用这个命令须要做为管理员登陆)。
5.老是有不止一种方法编写同一条SELECT语句。应该试验联结、并、子查询等,找出最佳的方法。
6.使用EXPLAIN语句让MySQL解释它将如何执行一条SELECT语句。
7.通常来讲,存储过程执行得比一条一条地执行其中的各条MySQL语句更快
8.应该老是使用正确的数据类型。
9.决不要检索比需求还要多的数据。换言之,不要用SELECT *(除非你真正须要每一个列)。
10.有的操做(包括INSERT)支持一个可选的DELAYED关键字,若是使用它,将把控制当即返回给调用程序,而且一旦有可能就实际执行该操做。
11.在导入数据时,应该关闭自动提交。你可能还想删除索引(包括FULLTEXT索引),而后在导入完成后再重建它们。
12.必须索引数据库表以改善数据检索的性能。肯定索引什么不是一件微不足道的任务,须要分析使用的SELECT语句以找出重复的 WHERE和ORDER BY子句。若是一个简单的WHERE子句返回结果所花的时间太长,则能够判定其中使用的列(或几个列)就是须要索引的对象。
13.你的SELECT语句中有一系列复杂的OR条件吗?经过使用多条SELECT语句和链接它们的UNION语句,你能看到极大的性能改进。
14.索引改善数据检索的性能,但损害数据插入、删除和更新的性能。若是你有一些表,它们收集数据且不常常被搜索,则在有必要以前不要索引它们。(索引可根据须要添加和删除。)
15.LIKE很慢。通常来讲,最好是使用FULLTEXT而不是LIKE。
16.数据库是不断变化的实体。一组优化良好的表一下子后可能就面目全非了。因为表的使用和内容的更改,理想的优化和配置也会改变。
17.最重要的规则就是,每条规则在某些条件下都会被打破。