-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathMySQL笔记.md
3084 lines (2015 loc) · 93.6 KB
/
MySQL笔记.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
- [一、了解SQL](#一了解sql)
- [数据库基础](#数据库基础)
- [什么是数据库](#什么是数据库)
- [表](#表)
- [列和数据类型](#列和数据类型)
- [行](#行)
- [主键](#主键)
- [什么是SQL](#什么是sql)
- [二、MySQL简介](#二mysql简介)
- [什么是MySQL](#什么是mysql)
- [客户机-服务器软件](#客户机-服务器软件)
- [MySQL版本](#mysql版本)
- [MySQL工具](#mysql工具)
- [mysql命令行实用程序](#mysql命令行实用程序)
- [MySQL Administrator](#mysql-administrator)
- [MySQL Query Broswer](#mysql-query-broswer)
- [三、使用MySQL](#三使用mysql)
- [连接](#连接)
- [连接](#连接-1)
- [了解数据库和表](#了解数据库和表)
- [四、检索数据](#四检索数据)
- [SELECT语句](#select语句)
- [检索单个列](#检索单个列)
- [检索多个列](#检索多个列)
- [检索所有列](#检索所有列)
- [检索不同的行](#检索不同的行)
- [限制结果](#限制结果)
- [使用完全限定的表名](#使用完全限定的表名)
- [五、排序检索数据](#五排序检索数据)
- [排序数据](#排序数据)
- [按多个列排序](#按多个列排序)
- [指定排序方向](#指定排序方向)
- [六、过滤数据](#六过滤数据)
- [使用WHERE子句](#使用where子句)
- [WHERE子句操作符](#where子句操作符)
- [检查单个值](#检查单个值)
- [不匹配检查](#不匹配检查)
- [范围值检查](#范围值检查)
- [空值检查](#空值检查)
- [七、数据过滤](#七数据过滤)
- [组合WHERE 子句](#组合where-子句)
- [AND 操作符](#and-操作符)
- [OR 操作符](#or-操作符)
- [计算次序](#计算次序)
- [IN 操作符](#in-操作符)
- [NOT操作符](#not操作符)
- [八、使用通配符进行过滤](#八使用通配符进行过滤)
- [LIKE操作符](#like操作符)
- [百分号(%)通配符](#百分号通配符)
- [下划线(\_)通配符](#下划线_通配符)
- [通配符使用技巧](#通配符使用技巧)
- [九、用正则表达式进行搜索](#九用正则表达式进行搜索)
- [正则表达式简介](#正则表达式简介)
- [使用正则表达式](#使用正则表达式)
- [基本字符匹配](#基本字符匹配)
- [同时匹配多个字符中任意一个](#同时匹配多个字符中任意一个)
- [匹配几个字符之一](#匹配几个字符之一)
- [匹配范围](#匹配范围)
- [匹配特殊字符](#匹配特殊字符)
- [匹配字符类](#匹配字符类)
- [匹配多个实例](#匹配多个实例)
- [定位符](#定位符)
- [十、创建计算字段](#十创建计算字段)
- [计算字段](#计算字段)
- [字段拼接](#字段拼接)
- [执行算术计算](#执行算术计算)
- [十一、使用数据处理函数](#十一使用数据处理函数)
- [函数](#函数)
- [使用函数](#使用函数)
- [文本处理函数](#文本处理函数)
- [日期和时间处理函数](#日期和时间处理函数)
- [数值处理函数](#数值处理函数)
- [十二、汇总数据](#十二汇总数据)
- [汇集函数](#汇集函数)
- [AVG()函数](#avg函数)
- [COUNT()函数](#count函数)
- [MAX()函数](#max函数)
- [MIN()函数](#min函数)
- [SUM()函数](#sum函数)
- [聚焦不同值](#聚焦不同值)
- [组合聚集函数](#组合聚集函数)
- [十三、分组数据](#十三分组数据)
- [数据分组](#数据分组)
- [创建分组](#创建分组)
- [过滤分组](#过滤分组)
- [分组和排序](#分组和排序)
- [SELECT子句顺序](#select子句顺序)
- [十四、使用子查询](#十四使用子查询)
- [子查询](#子查询)
- [使用子查询进行过滤](#使用子查询进行过滤)
- [作为计算字段使用子查询](#作为计算字段使用子查询)
- [十五、联结表](#十五联结表)
- [联结](#联结)
- [关系表](#关系表)
- [为什么要使用联结](#为什么要使用联结)
- [创建联结](#创建联结)
- [WHERE子句的重要性](#where子句的重要性)
- [内部联结](#内部联结)
- [联结多个表](#联结多个表)
- [十六、创建高级联结](#十六创建高级联结)
- [使用表别名](#使用表别名)
- [使用不同类型的联结:](#使用不同类型的联结)
- [自联结](#自联结)
- [自然联结](#自然联结)
- [外部联结](#外部联结)
- [使用带聚集函数的联结](#使用带聚集函数的联结)
- [使用联结和条件联结](#使用联结和条件联结)
- [十七、组合查询](#十七组合查询)
- [组合查询](#组合查询)
- [创建组合查询](#创建组合查询)
- [使用UNION](#使用union)
- [UNION规则](#union规则)
- [包含或取消重复的行](#包含或取消重复的行)
- [对组合查询进行排序](#对组合查询进行排序)
- [十八、全文本搜索](#十八全文本搜索)
- [理解全文本搜索](#理解全文本搜索)
- [使用全文本搜索](#使用全文本搜索)
- [启用全文本搜索支持](#启用全文本搜索支持)
- [进行全文本搜索](#进行全文本搜索)
- [使用查询扩展](#使用查询扩展)
- [布尔文本搜索](#布尔文本搜索)
- [全文本搜索的使用说明:](#全文本搜索的使用说明)
- [十九、插入操作](#十九插入操作)
- [数据插入](#数据插入)
- [插入完整的数据](#插入完整的数据)
- [插入多个行](#插入多个行)
- [插入检索出的数据](#插入检索出的数据)
- [二十、更新和删除数据](#二十更新和删除数据)
- [更新数据](#更新数据)
- [删除数据](#删除数据)
- [更新和删除的指导原则](#更新和删除的指导原则)
- [二十一、创建和操纵表](#二十一创建和操纵表)
- [创建表](#创建表)
- [表创建基础](#表创建基础)
- [使用NULL值](#使用null值)
- [主键再介绍](#主键再介绍)
- [使用AUTO\_INCREMENT](#使用auto_increment)
- [指定默认值](#指定默认值)
- [引擎类型](#引擎类型)
- [更新表](#更新表)
- [删除表](#删除表)
- [重命名表](#重命名表)
- [二十二、使用视图](#二十二使用视图)
- [视图](#视图)
- [为什么要使用视图](#为什么要使用视图)
- [视图的规则和限制](#视图的规则和限制)
- [使用视图](#使用视图)
- [利用视图简化联结](#利用视图简化联结)
- [用视图重新格式化索引出的数据](#用视图重新格式化索引出的数据)
- [用视图过滤不想要的数据](#用视图过滤不想要的数据)
- [使用视图和计算字段](#使用视图和计算字段)
- [更新视图](#更新视图)
- [二十三、使用存储过程](#二十三使用存储过程)
- [存储过程](#存储过程)
- [为什么要使用存储过程](#为什么要使用存储过程)
- [使用存储过程](#使用存储过程)
- [执行存储过程](#执行存储过程)
- [创建存储过程](#创建存储过程)
- [删除存储过程](#删除存储过程)
- [使用参数](#使用参数)
- [建立智能存储过程](#建立智能存储过程)
- [检查存储过程](#检查存储过程)
- [二十四、使用游标](#二十四使用游标)
- [游标](#游标)
- [使用游标](#使用游标)
- [创建游标](#创建游标)
- [打开和关闭游标](#打开和关闭游标)
- [使用游标数据](#使用游标数据)
- [二十五、使用触发器](#二十五使用触发器)
- [触发器](#触发器)
- [创建触发器](#创建触发器)
- [删除触发器](#删除触发器)
- [二十六、管理事务处理](#二十六管理事务处理)
- [事务处理](#事务处理)
- [控制事务处理](#控制事务处理)
- [使用ROLLBACK](#使用rollback)
- [使用COMMIT语句](#使用commit语句)
- [使用保留点](#使用保留点)
- [更改默认的提交行为](#更改默认的提交行为)
- [二十七、全球化和本地化](#二十七全球化和本地化)
- [字符集和校对顺序](#字符集和校对顺序)
- [使用字符集和校对顺序](#使用字符集和校对顺序)
- [二十八、安全管理](#二十八安全管理)
- [访问控制](#访问控制)
- [管理用户](#管理用户)
- [创建用户账号](#创建用户账号)
- [删除用户账号](#删除用户账号)
- [设置访问权限](#设置访问权限)
- [更改口令](#更改口令)
- [二十九、数据库维护](#二十九数据库维护)
- [备份数据](#备份数据)
- [进行数据库维护](#进行数据库维护)
- [诊断启动问题](#诊断启动问题)
- [查看日志](#查看日志)
- [三十、改善性能](#三十改善性能)
> 《mysql必知必会》读书笔记
目录完全按照mysql必知必会来
一、了解SQL
===========
数据库基础
----------
在深入了解MySQL之前有必要了解数据库的基础知识
### 什么是数据库
数据库是一种以某种方式有组织的方式存储的数据集合
理解数据库:将数据库想象成一个文件柜,此文件柜是一个存储文件的物理位置,不用管数据是如何存放的以及以什么方式存放的
:key:**数据库**(database):保存有组织的数据的容器(通常是一个或者一组文件)
> :warning::人们通常用数据库这个术语来表示他们使用的数据库软件,这是引起混淆的根源,数据库软件应该被称为DBMS(数据库管理系统),数据库是通过DBMS来操纵的容器,数据库是什么并不重要,因为你使用的是DBMS,他替你访问数据库。
### 表
表是一种结构化的文件,可以用来存储某种特定类型的数据
:key:**表**(table):某种特定类型数据的结构化清单
存储于表中的数据应该是一种类型的数据或者是一个清单,绝不是根据业务逻辑将多个清单混合存入一个表中,这样会使得以后的检索和访问都很困难
数据库中的每个表都有一个唯一的名字
> :warning::表名的唯一性取决于多个因素,例如数据库名,在不同的数据库中可以存在同名的表
表具有某些特性,描述表的这些信息就是所谓的模式,模式可以用来描述数据库中特定的表以及整个数据库和其中表的关系
:key::**模式**(schema):关于数据库和表的布局及特性的信息
> 有时候,模式用作数据库的近义词,模式的含义在上下文中不是很清晰
### 列和数据类型
表由列构成,列中存储表的各方面信息
:key::**列**(column):表中的一个字段,所有的表都是由一个列或多个列组成
正确得将数据分解成多个列及其重要,如果处理不好可能造成排序和过滤非常苦难
每个列都具有相应的数据类型
:key:**数据类型**(datatype):所容许的数据类型,每个列都具有相应的数据类型,它限制(容许)该列中存储的数据
### 行
:key:**行**(row):表中的一个记录
> 经常提到行(row)时将其称为数据库记录(record),很大程度上这两个术语是可以相互替代的,但从技术层面上来说行更规范
### 主键
表中的每一行都应该有可以唯一标识自己的一列(或一组列)
:key:**key**(primary
key):一列**(或一组列)**,其值能唯一区分表中的每一行
主键可以中来标识特定的一行,没有主键,更新和删除表中的某一特定行就很困难,因为有可能直接删除了多行
> 设计人员都应该保证他们创建的每个表都具有一个主键,以便于以后的数据操作和管理
只要满足一下条件,该列即可作为主键:
- 任意两行都不具有相同的主键值
- 每一行都必须要具有一个主键值(即主键值不能为NULL)
> 这里的规则是MYSQL本身强制施行的
主键通常作用在表的一个列上,但也可以使用多个列作为主键,使用多列作为主键时,上述条件作用于主键的所有列,但第二点有所改变,只需要列值的组合唯一即可(不需要保证单个列的值唯一)
> 除以上MySQL强制要求的几点之外,应该还有以下好习惯:
>
> - 不更新主键列中的值
> - 不重用主键列的值
> - 不将可能更改的列定义为主键:例如如果使用供应商的名字作为主键,那么当供应商合并或者更改名字时,主键也要随之改变,不合理
还有一个重要的键:外键
什么是SQL
---------
SQL是结构化查询语言(Structured Query
Language)的缩写,SQL是一门专门永安里和数据库通信的语言,与其他的编程语言不同,SQL只有很少的关键字,这是为了提供一种从数据库中读写数据的简单有效的方法。
SQL优点:
- SQL不是某个特定数据库提供商专有的语言,几乎所有的DBMS都支持SQL
- SQL简单易学,都是用少量简单的英文单词描述
- SQL灵活性高,可以进行复杂和高级的数据库操作
> 事实上任意两个DBMS实现的SQL都不完全相同,虽然他们绝大多数语法相同,所以SQL语句不是可以完全移植的
二、MySQL简介
=============
什么是MySQL
-----------
数据的所有存储,检索,管理和处理实际上是由数据库软件------DBMS来完成的,MySQL即是一种DBMS,他是一种数据库管理软件
MySQL的优点:
- 成本低:开源的,一般可以免费使用和免费修改
- 性能:MySQL执行非常快
- 可信赖:很多公司和站点都使用的是MySQL
- 简单:易于安装和使用
唯一缺点:不总是支持其他DBMS提供的功能和特性,这一步也在随着版本提升而改善
### 客户机-服务器软件
DBMS分为两类:
- 基于文件共享系统的DBMS
- 基于客户机-服务器的DBMS
前者包括微软的Access和FileMaker,一般用于桌面用途,不具有高可靠性
后者包括MySQL,Oracle以及SQL
Server,将其分为两个部分,服务器部分是负责数据访问和处理的一个软件,运行在被称为数据库服务器的计算机上
客户机通过向服务器发送网络请求给服务器,进行数据处理并且返回数据(如果有返回值的话)
大多数网络连接都不具备对数据的访问权,甚至不具备对存储数据的驱动器的访问权,只是通过MySQL进行了交互
- 服务器软件为MySQL DBMS
- 客户机可以是MySQL提供的工具,脚本语言(Perl),web应用开发语言(JSP,PHP),程序设计语言(C,C++,Java)等
### MySQL版本
主要是DBMS版本引入的更改:
- 4:InnoDB引擎,事务处理,并,改进全文本搜索
- 4.1:函数库,子查询,集成帮助
- 5:存储过程,触发器,游标,视图
MySQL工具
---------
客户端工具推荐
### mysql命令行实用程序
使用注意点:
- 命令输入在\>mysql之后(你也无法输入在前面)
- 命令用;或者`\g结尾`{=tex},不是Enter
- 输入help获取帮助(help select 获取 SELECT语句的帮助)
- 使用quit或者exit来退出命令行实用程序
>
> 即使你选择了使用后面所述的某个图形工具,也必须保证熟悉mysql命令行实用程序
### MySQL Administrator
MySQL官方提供的图形交互客户机,需要单独安装
### MySQL Query Broswer
MySQL官方提供的图形交互客户机,用来编写和执行MySQL命令
三、使用MySQL
=============
连接
----
如果你使用的是本地服务器,并且试用MySQL,使用root登陆就可以了,但是在实际开发中需要用户列表,权限关联等操作来提升数据库的安全性
可以使用流行的navicat客户端来进行用户图形化操作
连接到MySQL需要以下信息:
- 主机名:本地就是localhost
- 端口,一般是3306
- 合法用户名
- 用户口令(密码)【如果需要】
以下均使用命令行工具来操作
连接
----
最初连接到MySQL,没有任何数据库打开让你使用,需要使用USE关键字来选择数据库
``` {.mysql}
USE (数据库表名);
```
:key: 关键字(key
word):MySQL语言的保留字,不要使用mysql关键字去命名表和列
### 了解数据库和表
展示数据库和表
``` {.mysql}
SHOW DATABASES;
SHOW TABLES;
```
SHOW同样也可以用来展示列:
``` {.mysql}
SHOW COLUMNS FROM USER;
```
> SQL语句一般关键词用大写,自定义的表名或者数据库名用小写,尽管SQL是不区分大小写的,查询user表用以上语句不会报错
可以显示字段名,数据类型,是否允许为NULL,键信息,是否为auto\_increment等
> 自动增量:
>
>
> 某些表需要使用唯一值来作为主键,可以代替手动分配唯一值,可以在create表格的时候b把它当作表定义的组成部分
> 上述语句可以使用DESCRIBE语句来代替,即DESCRIBE user是SHOW COLUMNS FROM
> user的简写
所支持的其他SHOW语句还有
- SHOW STATUS:显示服务器状态
- SHOW GRANTS:显示用户和其具有的权限
- SHOW ERRORS 和 SHOW WARNINGS:显示服务器错误或警告消息
更多SHOW语句用法可以执行HELP SHOW语句来查看
四、检索数据
============
如何使用SELECT 语句检索出一个或多个数据列
SELECT语句
----------
SELECT是非常常用的关键字
使用SELECT关键字必须给出两条信息:想选择什么,以及从什么地方选择
检索单个列
----------
![image-20200322210728532](images/image-20200322210728532.png)
假设表的结构如图所示
检索username这一列
``` {.mysql}
SELECT username FROM user;
```
即可,标准格式`SELECT (COLUMNS) FROM (TABLE)`
> 数据没有排序,输出的结果可能是数据被添加到表里面的顺序,也可能不是,只要返回相同的数目即是正常的
因为SQL语句(至少mysql)是遇到分号才算一条语句的结束,所以可以将一条语句拆分成多行(也是非常推荐的),这样便于阅读。
检索多个列
----------
数据表还是如上图,假设要检索username和password这两个列
``` {.mysql}
SELECT username,password FROM user
```
SQL语句一般返回原始的,无格式的数据,至于数据的格式化问题,转换问题则是要在业务层中解决
检索所有列
----------
使用通配符的方式来解决 \*代表任意
``` {.mysql}
SELECT * FROM user
```
> :warning::除非你要检索数据的每个列,最好别用\*通配符,虽然省事儿,但是检索不需要的列通常会降低程序的性能
检索不同的行
------------
如果检索单列,只需要MySQL返回不同的值
使用DISTINCT(不同的)关键字即可,如检索username,只要不重复的,用法如下
``` {.mysql}
SELECT DISTINCT username FROM user;
```
会返回不同结果的username
DISTINCT关键字直接作用于所有列,而不是他后面的那个列,如
``` {.mysql}
SELECT DISTINCT username,password FROM user;
```
唯有username和password都相同的列才会被省去
限制结果
--------
限制SELECT的输出结果(只取前几行),使用LIMIT关键字
``` {.mysql}
SELECT * FROM user LIMIT 5;
```
至多返回5行数据,如果不足5行则直接返回
为了方便演示,使用Java插入了一些数据,便于查询
数据截图:
![image-20200322215536498](images/image-20200322215536498.png)
1\~3的id已经被使用了,即使被数据被删除了也不能再次使用【主键的规则】
使用上述limit语句查询显示4\~8的id数据
> :warning:: mysql的行索引是从零开始的
所以`SELECT * FROM user LIMIT 5`查询的是行索引为0\~4的数据
使用`SELECT * FROM user LIMIT a,b`查询的是行下标从5开始后的五个数据
使用完全限定的表名
------------------
迄今为止使用的SQL例子都只是列名引用列,也可以使用完全限定的名字来限定列:
``` {.mysql}
SELECT user.id FROM user LIMIT 5;
```
也可以限定表名字
``` {.mysql}
SELECT user.id FROM test.user LIMIT 5;
```
通过 `表名.列名` 或者 `数据库名.表名` 来完全限定
五、排序检索数据
================
使用SELECT 的 ORDER BY 子句,根据需要排序检索出的数据
排序数据
--------
使用 `SELECT * FROM user`
检索出的数据并不是纯粹的随机排列,如果不排序,数据一般都是按照它在底层表中出现的顺序显示,也就是数据插入的数据,但是如果后来对数据进行了更新或者删除的话,则此顺序会受到MySQL回收存储空间的影响,因此,如果不明确控制,不能依赖默认的排列顺序
:key:**子句**(clause):SQL语句由子句构成,一个子句通常包括一个关键字和所提供的数据组成,有些子句是必须的,有些子句是可选的
像 `SELECT * FROM user LIMIT 5`
的SELECT语句的FROM子句就是必须的,而LIMIT子句就是可选的,此ORDER BY
子句就是可选的:
``` {.mysql}
SELECT * FROM user ORDER BY username LIMIT 10;
```
> 默认是升序排列,一般ORDER BY的字段都是检索的字段,但是ORDER
> BY没有检索的字段也是完全合法的
按多个列排序
------------
经常会出现这种情况,如果显示雇员清单,由姓和名两列(首先按照性排列,在每个性中再按照名排列),实现此功能只需要指定列名,列名之间用逗号隔开即可
``` {.mysql}
SELECT first_name,last_name FROM user ORDER BY first_name,last_name;
```
会先按照firstname排序,再通过lastname排序firstname相同的数据
如果firstname都是唯一的,则不用对lastname进行排序
指定排序方向
------------
默认是升序排序,如果要使用降序排序,则使用DESC关键字即可
按照降序排列username:
``` {.java}
SELECT * FROM user ORDER BY username DESC LIMIT 10;
```
DESC和DISTINCT关键字不同,DISTINCT关键字会作用于所有的列,让其都保持唯一,而DESC则只会保持其前面的列是降序的,其余列都是保持默认的升序
> 如果想让多个列都进行降序排列,则必须在每个列上都指定DESC关键字
默认的升序排列关键字是ASC,但是ASC用的非常的少,因为默认就是ASC的
> 区分大小写的排序设置:因为MySQL是不区分大小写的,所以A和a的排列地位是一样的,如果要进行区分,需要数据库管理员对数据库进行配置,用简单的ORDER
> BY是做不到的
使用ORDER BY找出id最大的值
``` {.mysql}
SELECT id FROM user ORDER BY id LIMIT 1;
```
先按照id降序排列,再取最上面一个即获取到id的最大值
> 子句会有位置的问题,例如:只有按照 FROM子句 + ORDER BY 子句 + LIMIT
> 子句才不会报错,否则会报错
六、过滤数据
============
使用SELECT语句的WHERE子句来指定搜索条件
使用WHERE子句
-------------
很少需要检索表中的所有行,往往只需要指定指定搜索条件,也叫过滤条件
``` {.mysql}
SELECT * FROM user WHERE id = 0;
```
WHERE子句不止仅能进行相等判断
> SQL过滤和应用过滤:
>
> 数据也可以再客户端这边过滤,即服务器端仅仅返回所有数据,然后再客户端这边去处理,这种实现很不令人满意,不仅会让客户机的效率大大降低,还会导致网络的数据传输量加大,造成带宽的浪费
> 子句的排列顺序为:FROM WHERE ORDER BY LIMIT
WHERE子句操作符
---------------
操作符 说明
--------- --------------------
= 等于
\<\> 不等于
!= 不等于
\< 小于
\<= 小于等于
\> 大于
\>= 大于等于
BETWEEN 再指定的两个词中间
### 检查单个值
``` {.mysql}
SELECT * FROM user WHERE username = 'ECAC3';
```
> 使用单引号和双引号的效果相同
``` {.mysql}
SELECT * FROM user WHERE id < 10;
```
### 不匹配检查
``` {.mysql}
SELECT * FROM user WHERE id <> 10;
```
等价于
``` {.mysql}
SELECT * FROM user WHERE id != 10;
```
### 范围值检查
可以使用BETWEEN关键字,不过于其他WHERE子句的操作符稍有不同
``` {.mysql}
SELECT * FROM user WHERE id BETWEEN 5 AND 10;
```
> BETWEEN a AND b
>
> 一定是查询大于等于a小于等于b的值
以上语句等价于:
``` {.mysql}
SELECT * FROM user WHERE id >= 5 AND id <= 10;
```
### 空值检查
设计表时候即可指定这个字段能否为NULL
:key: :NULL 无值(no value),与包含字段0,空字符串不同
SELECT由一种特殊的WHERE子句来检查具有空值的NULL
``` {.mysql}
SELECT * FROM user WHERE password IS NULL;
```
> :warning::在匹配过滤和不匹配过滤中都不会返回当前列为NULL的行
七、数据过滤
============
使用 WHERE 子句建立更强大的查询功能,和NOT 和 IN操作符
组合WHERE 子句
--------------
MySQL允许给出多个WHERE 子句,给出两种使用方式:以AND 子句或者以OR
子句的方式使用。
:key: **操作符**(operator):用来连接或该表WHERE
子句中的子句关键字,也成为逻辑操作符
### AND 操作符
上面的那个user表不是很好用
![image-20200323131044433](images/image-20200323131044433.png)
新建一个product表,字段如下:
![image-20200323131115068](images/image-20200323131115068.png)
并在其中插入大量数据(Java操作,使用并发编程极大的提升了效率)
AND操作符:查询商品价格大于50的并且ID小于50的商品名称
``` {.mysql}
SELECT price FROM product WHERE id < 50 AND price > 50;
```
:key: **AND**:用在WHERE子句中的关键字,用来指定检索满足所有给定条件的行
> 上述条件只有两个,如果有多个,则必须都使用AND进行连接
### OR 操作符
指定MySQL检索匹配任一条件的行
如果需要检索price大于50或者ID小于50的商品名称:
``` {.mysql}
SELECT name FROM product WHERE price > 50 OR id < 50;
```
:key: OR:WHERE子句的关键字,用来检索匹配任一给定条件的行
### 计算次序
可以结合AND和OR关键字来完成复杂的查询操作
AND关键字的优先级比OR高,有可能造成操作符的错误组合
例如:查询 id在 大于两百或小于20 价格大于50的商品详细信息
``` {.mysql}
SELECT * FROM product WHERE id >200 OR id < 20 AND price >50;
```
如果不做任何其余的处理,MySQL会理解成为查询id大于200的商品或者是
id小于20且价格大于50的商品,有歧义
解决方法:使用()来限定操作顺序
> 充分利用圆括号,不要过度的依赖于默认的计算次序,即使他确实是你想要的东西也是如此,使用圆括号没有坏处,能消除歧义
IN 操作符
---------
圆括号还可以结合IN 操作符,来指定条件取值
如要查询id为1,2,250的商品详细详细,可以使用IN 操作符
``` {.mysql}
SELECT * FROM product WHERE id IN (1,2,250);
```
以上语句等价于下列语句
``` {.mysql}
SELECT * FROM product WHERE id = 1 OR id = 2 OR id = 250;
```
使用IN 操作符的优点:
- 语法清楚直观
- 操作次序易管理(减少了操作符的数量)
- 比OR操作的执行效率高
- 可以包含其他SELECT 语句
:key: **IN** :WHERE子句的指定匹配值的关键字,功能与OR相当
### NOT操作符
:key: NOT:WHERE子句中用来否定后跟条件的关键字
例子:用来列出id除1和2以外的所有商品
``` {.mysql}
SELECT * FROM product WHERE id NOT IN (1,2);
```
> mysql中的NOT关键字只支持对IN,BETWEEN和EXISTS子句取反,与其他的DBMS有很大的差距
八、使用通配符进行过滤
======================
LIKE操作符
----------
前面介绍的操作符都是对已知的数据进行过滤,这种过滤方法很有局限性,例如如何查找名字
中包含a的产品,可以构造一个**通配符搜索模式**来解决这个问题
:key: 通配符(wildcard):用来匹配值的一部分的特殊字符
:key:搜索模式(search pattern):由字面值,通配符构成的搜索条件
为在搜索模式中使用通配符,必须使用LIKE关键字
### 百分号(%)通配符
最常用的通配符就是%,他表示任意字符出现任意次数(可以出现0次)
检索a开头的商品的详细详细:
``` {.mysql}
SELECT * FROM product WHERE name LIKE 'a%';
```
> 以上SQL语句可以匹配到名字为a的商品
检索名字中包含a3的商品的详细详细
``` {.mysql}
SELECT * FROM product WHERE name LIKE '%a3%';
```
检索以2开头,以1结尾的商品的详细信息
``` {.mysql}
SELECT * FROM product WHERE name LIKE "2%1";
```
:warning::即使通配符%可以匹配任何字段,但也没法匹配NULL
### 下划线(\_)通配符
\_只能匹配单个字符,不能多也不能少
``` {.mysql}
SELECT * FROM product WHERE id LIKE "23a31_";
```
通配符使用技巧
--------------
通配符很有用,但是有代价的,通配符花费的时间一般比其他搜索的时间更长
下面给出一些使用技巧:
- 尽量使用其他操作符,不要过分依赖通配符
- 除非真的有必要,否则不要把通配符置于搜索模式的开始处,效率会比较低
- 仔细确定通配符的位置
九、用正则表达式进行搜索
========================
正则表达式简介
--------------
前面的通配符对于基本的过滤是够用了,但是随着过滤条件的增加,WHERE子句本身的复杂性也会增加
正则表达式(regexp)可以用来匹配文本的特殊的串,正则表达式也广泛用于程序设计,文本编辑器,操作系统等
使用正则表达式
--------------
MySQL可以使用正则表达式,过滤SELECT检索出的数据
> MySQL仅支持正则表达式的一个很小的子集
### 基本字符匹配
检索包含a字符的商品的详细信息
``` {.mysql}
SELECT * FROM product WHERE name REGEXP "a";
```
当然,这个例子也可以轻松使用LIKE去完成,甚至效率会更高,但是某些情况必须要用到正则表达式(例如只允许匹配到数字,通配符是不提供这个功能的)
> LIKE和REGEXP的区别:
>
> - SELECT \* FROM product WHERE name LIKE "1000";
> - SELECT \* FROM product WHERE name REGEX "1000";
>
> 第一条语句只会返回name为1000的数据(没有通配符)
>
> 而第二条语句会返回包含1000的name的数据,如果要第二条语句也像第一条语句一样只返回name为1000
> 的数据,则需要使用到\^和\$定位符
### 同时匹配多个字符中任意一个
为搜索两个串之一,可以使用 \| 操作符,例子:
匹配name中包含d3或者23的字符
``` {.mysql}
SELECT * FROM product WHERE name REGEXP "d3|23";
```
| 为正则表达式的OR操作符,如果有多个OR条件,则使用多个\| 如 WHERE name
REGEXP "d3\|23\|33";
### 匹配几个字符之一
如果想匹配指定的几个字符之一,则使用\[和\]来完成
例如,想检索id 为 11,21,31的商品详细信息
``` {.mysql}
SELECT * FROM product WHERE id REGEXP "[123]1";
```
但是会检索出id为210的数据 :laughing:例子举的不好,大概这个意思把
### 匹配范围
如果要匹配数字0\~9,可以使用\[0123456789\]去进行匹配,为简化,可以使用-,上述式子等价于\[0-9\]
例如:
``` {.mysql}
SELECT * FROM product WHERE id REGEXP "[1-2][5-6][7-8]"
```
即可匹配到名字中包含157,158,167,168,257,257,267,268的数据
也可以指定匹配a到z的字符,如下:\[a-z\]
### 匹配特殊字符
如果要匹配名字中包含.的商品,使用如下SQL语句
``` {.mysql}
SELECT * FROM product WHERE name REGEXP ".";
```
则会返回所有,因为.可以匹配任意字符
正确SQL语句为:
``` {.mysql}
SELECT * FROM product WHERE name REGEXP “\\.”
```
正则表达式里面具有特殊意义的字符都需要使用\\`\来转义`{=tex},有些字符转义后也会有特殊的意义,如:
![image-20200323143548247](images/image-20200323143548247.png)
> 如果是要匹配 的话,则需要使用 来匹配
### 匹配字符类
为简化常用的匹配规则,将其抽取出来成为字符类
![image-20200323143900584](images/image-20200323143900584.png)
:warning::有些地方用不了,尽量少用
### 匹配多个实例
到目前为止正则表达式还只能匹配到单个的字符,如果要同时匹配99个s,你不可能写99个s到正则表达式中把,可以使用重复元字符来进行更强的控制
元字符 说明
-------- ------------------------------
\* 0或多个字符
\+ 1或多个字符,等价{1,}
? 0或1个字符,等价{0,1}
{n} 指定数目的匹配
{n,} 不少于指定数目的匹配
{m,n} 匹配指定的范围(m不超过255)
- 如果要匹配 (1 stick) 和 (5 sticks)
使用如下正则表达式
``` {.regexp}
\\([0-9] sticks?\\)
```