1. 数据库介绍
数据库,就是能够存储和管理“大量数据”的一种软件系统的统称。
1.1. 主流数据库
主流数据库包括:MS SQL Server, Oracle,DB2,Informix, Sybase等。
他们都是被称为“关系数据库”的一种遵循sql标准的软件产品。
1.2. MySQL数据库概览
MySQL数据库的基本结构如下所示:
其中,实际表的数据和结构如下所示:
对应的几个名词(单词)为:
DBMS: 数据库(管理)系统,是我们“安装”而得到的。
DB,DataBase: 数据库,一个数据库系统中可以存放多个数据库。
通常一个项目(网站)使用一个数据库来存储其中的数据。
table:表,一个数据库中可以存放多个表。
row:行,指一行数据,一个表中可以有很多行。
record:记录,也是指一行数据。
column:列,指一列数据,一个表可以有若干列。
field:字段(列名),指数据表中的一列的名称(类似表头),一个表可以有若干字段。
1.3. 关系数据库
关系数据库是指基于关系模型而设计的数据库系统。
所谓关系,其实就是指一个二维表(table)(有行有列)。
一行有多个数据,就表示这多个数据是具有内在关系的(同属一个“实体”)。
比如,上述两个表,可以用“E-R”图(实体-关系图)表示如下:
2. 访问mysql数据库服务器
通常,我们要把数据库理解为“你用,还是不用,它就在那里!”
2.1. 开启/关闭数据库服务
2.1.1. 通过系统服务
2.1.2. 通过命令行方式
在管理员模式下运行cmd,执行如下命令:
net start mysql
net stop mysql
2.2. 客户端连接数据库服务器
数据库就在那里!连,还是不连,就看你了!
任何连接或访问数据库的“软件/工具”,都可以称为“客户端”。
2.2.1. 命令行连接数据库
连接(进入)数据库命令:
mysql -h主机地址 -u用户名 -p
特别注意:cmd中登录后,请立即使用“set names gbk;” 语句来设定连接编码。
表示当前连接到数据库的“客户端”的字符编码是gbk(固定的,不可更改)。
退出数据库命令:
quit;
或
exit;
或
\q;
2.2.2. navicat软件连接数据库
安装它,然后打开软件:
2.2.3. phpmyadmin“网站”连接数据库
安装(配置)该站点:
1, hosts文件中设定域名解析: www.myadmin69.com
2, 拷贝网站文件到指定目录: bj-php-69/myadmin/
3, httpd-vhost.conf文件中设定站点:
<VirtualHost *:80>
.......
</VirtualHost>
3. 数据库操作
3.1. 查看所有数据库
语句形式:
show databases;
一个错误提示:
3.2. 创建新数据库
语句形式:
create database 数据库名 [charset 字符集名称] [collate 校对规则名];
字符集名类似这些: utf8, gbk, gb2312, big5, ascii等。推荐用utf8。
校对规则名:通常都不用写,而是使用所设定字符集的默认校对规则。
校对规则的含义:
就是一个字符集中的每个字符的“排序规则”。
对于英文,很简单,就是按英文单词的字母顺序。
对于中文,或其他一些亚洲语言,就会面临问题:两个字的顺序,到底谁先谁后(谁大谁小)呢?
比如:“传”和“智”,有这样的可能排序方式:
按拼音:“传”在前(更小),“智”在后(更大);
按笔顺(横竖撇捺折):“智”在前(更小),“传”在后(更大);
按编码:肯定一个大一个小(具体未知);
查看可用的字符集:
show charset;
查看可用的校对规则:
show collation;
3.3. 查看数据库创建信息
语句形式:
show create database 数据库名;
结果其实就是能看到指定数据的完整创建语句(含默认值的选项,比如charset, collate)。
3.4. 删除现有数据库
语句形式:
drop database 数据库名;
3.5. 修改现有数据库
修改数据库,其实只是修改数据库的字符编码或校对规则。
其实一般都不需要修改。
语句形式:
alter database 数据库名 charset 新的字符集名称 collate 新的校对规则名 ;
3.6. 选择(使用)某个数据库
一个项目中,具体进行有关数据操作(增删改查)之前,都需要先“选择/进入”该数据库。
语句形式:
use 数据库名;
总结有关数据库的常规操作:
创建数据库:
create database 数据库名 charset 编码名(推荐utf8);
显示所有数据库:
show databases ;
显示某个数据库的创建语句:
show create database 数据库名;
删除数据库:
drop database 数据库名;
修改某个数据库(的字符集和排序规则)
alter database 数据库名 charset 新字符集名称 collate 新校对规则名;
使用(进入/选择)数据库:
use 数据库名;
4. 数据表操作
“数据库”只是一个外壳,除了有个数据库名称和字符集设定,基本就没有别的信息了。
数据表才是存储(装载)数据的具体“容器”。
我们需要创建不同的表来存储不同的数据。
4.1. 创建数据表初步
语句形式:
create table 数据表名 (字段1, 字段2, ... )[charset=字符集] [engine=表类型];
其中:
字段的形式为: 字段名 字段类型 [字段属性...]
字符集包括:utf,gbk,gb2312,big5等等,默认是数据库的字符集,可以不写。
表类型包括:InnoDB, MyIsam,BDB,等,默认是InnoDB,可以不写。
4.2. 查看所有数据表
语句形式:
show tables;
4.3. 查看数据表结构
语句形式:
desc 表名;
所谓数据表的结构,其实就是一个表的每个字段的具体信息。
在来一个:
4.4. 查看数据表的创建语句
语句形式:
show create table 表名;
(在phpmyadmin的界面执行的结果)
4.5. 删除数据表
语句形式:
drop table 表名;
有关表的基本操作的总结:
建表:
create table 表名 (
字段名 字段类型 [字段属性],
字段名 字段类型 [字段属性],
......
) [ charset=编码名称] [engine=表类型名称];
表类型名称可用的也就几个,比如: InnoDB(默认的), MyIsam, BDB, memory,
显示所有表:
show tables;
显示某个表的创建语句:
show create table 表名;
显示某个表的结构:
desc 表名;
删除表:
drop table 表名;
4.6. 修改数据表
修改数据表主要是修改表名,添加字段,修改字段,删除字段,修改表的字符集;
4.6.1. 添加字段:
语句形式:
alter table 表名 add 字段名 字段类型 [字段属性...] [after 某字段名 或first];
after 某字段名:意思是,新加的字段,放在该现有字段的后面;
first:表示新加的字段放在第一位(最前面)
4.6.2. 修改字段:
语句形式:
alter table 表名 change 旧字段名 新字段名 字段类型 [字段属性...];
如果不修改字段名,而只修改字段的其他信息,则可以使用:
alter table 表名 modify 要修改的字段名 字段类型 [字段属性...];
4.6.3. 删除字段:
语句形式:
alter table 表名 drop 要删除的字段名;
4.6.4. 修改表名:
语句形式:
alter table 表名 rename 新的表名;
4.6.5. 修改字符集:
语句形式:
alter table 表名 charset=新的字符集;
修改表语句的总结:
添加一个字段:
alter table 表名 add 一个字段的信息;
一个字段的信息的意思是:字段名 字段类型 [字段属性]
改掉一个字段:
alter table 表名 change 旧的字段名 新的字段信息;
修改一个字段:
alter table 表名 modify 要修改的字段名 新的类型 [新的属性]
删除字段:
alter table 表名 drop 要删除的字段名;
修改表名:
alter table 表名 rename 新的表名;
修改字符集:
alter table 表名 charset=新的字符集;
5. 数据操作初步
数据都是存储在数据表中。
数据的基本操作有4种:增(插入insert),删(删除delete),改(修改update),查(查询select)。
即所谓的 CRUD 操作: Create(创建), Retrieve(获取), Update(更新), Delete(删除)。
5.1. 插入数据
语句形式:
insert into 表名 (字段名1, 字段名2, ... ) values (数据1, 数据2, ... );
说明:
1,字段名和数据是“一一对应”的,包括:数量一致,顺序一致,类型匹配。
2,对于要写入的数据,字符串和时间日期类型,要用单引号引起来。
3,可以省略“字段列表”部分,此时就需要给出跟字段数量一样多的数据,类似这样:
① insert into 表名 values (数据1, 数据2, ... );
5.2. 查询数据
语句形式:
select 字段名1, 字段名2, ... from 表名 [ where 条件];
说明:
1,select后的字段列表用于设定要从表中取出的哪些字段的值。
2,select后可以只使用一个“*”号表示取出该表中所有字段的值。
3,where条件表示取出的数据所应满足的条件,比如:
① where id < 10 表示取出那些字段id的值小于10的行。
② where age > 60 表示取出那些字段age的值大于60的行
4,where条件可以不写,就取出所有行的数据。
5.3. 删除数据
语句形式:
delete from 表名 [where 条件];
说明:
1, 删除数据指的是删除表的某些行,比如原来有10行,可以将其中的3行删除,则剩下7行。
2, where条件表示删除数据所应满足的条件,含义跟select中的一样。
3, where 条件可以不写,如果不写,则会删除所有数据——通常都不会这么用。
5.4. 修改数据
语句形式:
update 表名 set 字段名1 = 新值1, 字段名2=新值2, ... [where条件];
说明:
1, 修改数据指的是修改表的某些行的某些字段。
2, where条件表示修改数据所应满足的条件,含义跟select中的一样。
3, where 条件可以不写,如果不写,则会修改所有数据——通常都不会这么用。
总结:
系统级操作:
服务器的启停
mysql服务,通过系统服务来操作,或:
net start mysql
net stop mysql
登录系统:
mysql -hlocalhost -uroot -p
退出:
quit
exit
客户端:
cmd方式:
phpmyadmin方式:
navicat方式:
库操作:
建库:
create database 数据库名 charset utf8 [collate 校对规则];
show charset; //显示所有可用的编码(字符集)
show collation; //显示所有可用的校对规则(排序规则)
删除数据库:
drop database 数据库名;
show databases;
show create database 数据库名;
use 数据库名;
表操作:
建表:
create table 表名 (
字段名1 类型 [属性],
字段名2 类型 [属性],
......
)
charset = 编码 engine =表类型名称
表类型有:InnoDB, MyIsam, BDB, Memory
表类型也叫做“存储引擎”
desc 表名;
show create table 表名;
show tables;
drop table 表名;
alter table 修改表有如下可修改项:
alter table 表名 add 新的字段;
alter table 表名 change 改掉字段;
alter table 表名 modify 修改字段;
alter table 表名 rename 新的表名;
alter table 表名 charset = 新的字符集名;
数据操作:
增:
insert into (字段列表) values (值列表);
删:
delete from 表名 where 条件;
改:
update 表名 set 字段名 = 新的值,..... where 条件
查:
select 字段列表 from 表名 where 条件。
6. MySQL数据类型
6.1. 数据类型(列类型)总览
可见,mysql中的数据类型,总体分3大类:
数字型:
时间型:
字符型:
其中,在sql语句中,数字型数据不需要单引号引起来,而时间型和字符型数据需要用单引号引起来。
6.2. 整型
整型数据类型包括:
tinyint :微整型
smallint :小整型
mediumint :中整型
int :整型
bigint :大整型
这些不同大小范围的整型信息如下表所示:
类型 | 所占空间 (字节) | 带符号 | 无符号 | ||
最小值 | 最大值 | 最小值 | 最大值 | ||
tinyint | 1 | -128 | 127 | 0 | 255 |
smallint | 2 | -32768 | 32767 | 0 | 65535 |
mediumint | 3 | -8388608 | 8388607 | 0 | 16777215 |
int | 4 | -2147483648 | 2147483647 | 0 | 4294967295 |
bigint | 8 | -9223372036854775808 | 9223372036854775807 | 0 | 18446744073709551615 |
默认整数类型是带符号的,即可以有正负值,比如:
create table zhengxing1(num1 int, num2 tinyint);
此时,num1和num2中都可以存储负数(但都不能超出范围)
不带符号的整数类型设置形式如下:
create table zhengxing2(num1 int unsigned, num2 tinyint unsigned);
6.3. 小数型
小数类型分为浮点小数和定点小数。
6.3.1. 浮点小数
浮点小数是“不精确的小数”,包括float和double。
float:
占用4字节存储空间,可称为“单精度浮点数”,约7位有效数字。
double:
占用8字节存储空间,可称为“双精度浮点数”,约17位有效数字。
6.3.2. 定点小数
定点小数是“精确的小数”——它通过内部技巧,突破了“有些小数无法用二进制精确表示”的局限。
其设定方式通常是这样的: decimal(M, D);
其中M表示该小数的总的有效位数(最大65),D表示该小数的小数点后的位数。
演示:
定义三个字段分别为float、double和decimal类型,并都插入数字“123456789.123456789123456789”,显示结果。
数据类型选择示例:
6.4. 日期时间型
日期时间类型包括如下几种:
date类型:
表示日期,格式类似这样:'0000-00-00'
time类型:
表示时间,格式类似这样:'00:00:00'
datetime类型:
表示日期时间,格式类似这样:'0000-00-00 00:00:00'
timestamp类型:
表示“时间戳”,其实就是一个整数数字,该数字是从是“时间起点”到现在为止的“秒数”。
“时间起点”是:1970-1-1 0:0:0
timestamp类型的字段,无需插入数据,而是会自动取得当前的日期时间(表示当前时刻)。
而且,此类型字段会在数据被更新时,也同样自动取得当前的日期时间(表示修改的时刻)。
特别总结:它在insert或update某行数据的时候,能够自动获得当前时间。
year类型:
表示年份,格式为:'0000'
注意:
时间类型的字面值,通常使用单引号引起来
示例:
创建一个表,设定5个字段分别为上述类型,并插入相应的数据值后查看结果。
now()函数的使用:
更新数据,以对比datetime类型的数据和timestamp类型的数据的区别:
小细节:timestamp类型在一个表中只能用于一个字段!
6.5. 字符串型
字符串类型常用的包括:char, varchar, text, enum, set,分述如下:
6.5.1. 定长字符char和变长字符varchar
定长字符类型char:
适用于存储的字符长度为固定长度的字符,比如中国邮政编码,中国身份证号码,手机号码等。
设定形式:
字段名称 char(字符个数)
其特点是:
1,存储的字符长度固定,最长可设定为255个字符。
2,如果实际写入的字符不足设定长度,内部会自动用空格填充到设定的长度。
3,相对varchar类型,其存取速度更快。
变长字符类型varchar:
适用于存储字符长度经常不确定的字符,比如姓名,用户名,标题,内容,等大多数场合的字符。
设定形式:
字段名称 varchar(字符个数)
其特点是:
1,存储的字符长度是写入的实际长度,但不超过设定的长度。最长可设定为65532(字节)。
(1) 注:由于其最长的限制是字节数,因此存储中文和英文的实际字符个数是不同的;
(2) 英文:一个字符占一个字节;
(3) 中文(gbk编码):一个字符占2个字节;
(4) 中文(utf8编码):一个字符占3个字节;
2,如果实际写入的字符不足设定的长度,就按实际的长度存储。
3,相对于char字符串,其存取速度相对更慢。
示例:
定义一个表,演示char和varchar的使用和区别:
思考题:
一个表中有一个字段为c1,其类型为char(10),另有一个字段为c2,类型为varchar,问:
c2最多可以设置多长?
答:
1,一个表中的行也有一个“最大字节长度的限制”,一行最多存储65532字节。
2,则此时,c2最多可以设置65532-10 = 65522(长度设定)
3,如果c2中存储的全是英文字符,就可以存储65522个
4,如果存储中文:
gbk:最多65522/2 = 32761个
utf8:最多65522/3 = 21840个
6.5.2. text长文本类型
适用于存储“较长的文本内容”,比如文章内容。最长可存储65535个字符。
如果还需要存储更长的文本,可以使用mediumtext(1600万左右)或longtext(40亿左右)。
设定形式:
字段名称 text
text类型的字段不能设置默认值。
text类型虽然是字符类型,但不能设置长度!!!
text类型的数据不存在行中。
6.5.3. enum和set类型
enum类型和set类型都是用于存储“有给定值的可选字符”,比如类似表单中的单选,多选,下拉列表。
enum类型(单选类型/枚举类型):
enum类型通常用于存储表单中的“单选项”的值。
设定形式:
enum(‘选项值1’, ‘选项值2’, ‘选项值3’, ....)
这些选项值都对应了相应的“索引值”,类似索引数组的下标,但是从1开始的。
即这些选项的索引值分别为:1, 2, 3, 4, .....
enum类型最多可设定65535个选项。
示例:
create table tab1 (id int, edu(‘大学’, ‘中学’, ‘小学’, ‘其他’ ) );
insert into tab1 (id, edu) values (1, ‘大学’);
或:
insert into tab1 (id, edu) values (1, 2); //表示中学
set类型(多选类型):
set类型通常用于存储表单中的“多选项”的值。
设定形式:
set(‘选项值1’, ‘选项值2’, ‘选项值3’, ....)
这些选项值都对应了相应的“索引值”,其索引值从1开始,并“依次翻倍”。
即这些选项的索引值分别为:1, 2, 4, 8, 16, ..... (其实就是2的n次方)
enum类型最多可设定64个选项值。
示例:
create table tab2 (aihao(‘篮球’, ‘排球’, ‘足球’, ‘中国足球’ ) ); #对应索引值为1,2,4,8
insert into tab2( aihao ) values ( ‘篮球’ );
或:
insert into tab2 ( aihao ) values ( ‘篮球,排球’ );
或:
insert into tab2 ( aihao ) values ( ‘篮球,足球,排球’ );
或:
insert into tab2 ( aihao ) values ( 2 ); //表示排球(2)
或:
insert into tab2 ( aihao ) values ( 3); //表示“篮球,排球”(1+2)
或:
insert into tab2 ( aihao ) values ( 7); //表示“篮球,排球,足球”(1+2+4)
基本示例:
使用索引值来插入数据:
7. 列属性
列属性是指定义或创建一个列的时候,可以给列额外增加的“附加特性”。
形式如下:
create table 表名 (列名 列类型 [列属性...] );
说明:
1,一个列可以有多个列属性;
2,多个列属性空格隔开就行;
列属性包括以下这些:
null,not null
设定为空,或非空,表明该列数据是否可为空值(null)。
default
用于设定列默认值(不给值或给空值null并not null,就会自动使用该值)。
使用形式:default 默认值 。
primary key
用于设定主键。
主键就是一个表中数据的“关键值”,通过该关键值就可以找到该特定的数据行。
一个表的主键值不能重复(相等),比如文章表中的文章编号id,比如用户表中的用户名。
主键字段必须有值(不能为空)。
一个表只能有一个主键(但一个主键可以是1个字段或2个以上的字段联合构成)
auto_increment
用于设定一个整数字段的值是“自增长的”,通常用于一个表中的数据行的编号(比如文章编号)。
默认情况下自增长值从1开始。
一个表只能设定一个字段为自增长特性。
unique key
用于设定“唯一键”的特性。
唯一键表示一个表中的某字段的值是“唯一的”,“不重复的”。
唯一键有点类似primay key,但其值可以为空(null)。
一个表可以有多个唯一键。
comment
用于设定字段的说明性内容,类似注释,但又不是注释(属于有效的代码)。
使用形式: comment ‘文字内容’
演示1:
演示:
创建一个表,并用上以上所有字段属性。字段可包括:id, kecheng, keshi, intro.
联合主键演示:
create table 表名(
字段名1 类型 [字段附加属性],
字段名2 类型 [字段附加属性],
....
primary key(xx1, xx2, ......),
unique key (xx1, xx2, .... )
)
charset= utf8/gbk -- 表中存储数据的字符编码
engine=InnoDB/MyIsam/BDB/Memory -- 表类型/存储引擎
类型:
数字类型:
整数:int, tinyint, smallint, mediumint, bigint
小数:float , double, decimal(M, D);
时间类型:
time, date, datetime, year, timestamp,
字符类型:
char: 定长字符,最大可设定255(字符个数)
varchar: 变长字符,最大可设定为65532个字符
text:长文本,不能设定长度,其中最长能存储65535个字符
enum:单选型字符,枚举字符,
enum(‘选项1’,’选项2’,’选项3’,....),他们每个选项对象的索引值为:1,2,3,4,5,6 ,.....
set:多选型字符,
set(‘选项1’,’选项2’,’选项3’,....),他们每个选项对象的索引值为:1,2,4,8,16 ,.....
属性:
not null 设定为非空数据
default 默认值
primary key 主键,一个表只能设置一个
unique key 唯一键
auto_increment 自增 用于整数,并且一个表只能设置一个
comment ‘说明文字’
8. 实体与实体的关系
8.1. 基本概念
实体(Entity):
指现实中具体存在的可指称的“某物”。
一个表中的一行数据实际就是指对某物的描述性数据,所以一行数据就是一个实体。
有时实体也指整个表(因为表是由多个实体构成的)。
实体间关系(relationship):
是指不同实体数据之间的关系,很多时候就是指表和表之间的关系。
实体间关系有:一对一关系,一对多关系,多对多关系。
图示如下:
8.2. 一对一关系
表示一个表跟另一个表之间的数据之间一对一的关系。图示如下:
现实案例:
学校表:id,校名, 地址, 校长id
校长表:id, 姓名, 年龄, 学历
此时,学校表和校长表就是一对一的关系:
一个学校只能有一个校长,一个校长只能负责一个学校。
8.3. 一对多关系
表示一个表跟另一个表之间的数据之间是一对多的关系。图示如下:
现实案例:
学校表:id,校名, 地址, 校长id
班级表:id, 班级名称, 教室号, 所属学校id
此时,学校表和班级表就是一对多的关系:
一个学校可以有多个班级,一个班级只能属于一个学校。
8.4. 多对多关系
表示一个表跟另一个表之间的数据之间是多对多的关系。图示如下:
现实案例:
课程表:id,课程名称, 课时数, 学分数
学生表:id, 姓名, 性别, 年龄, 所属班级id
此时,课程表和班级表就是多对多的关系:
一个课程可以被多个学生学习,
一个学生也可以学多个课程。
这种情况,通常还需要建立一个“中间表”,以记录所有学生各自选修了哪些课程,如下所示:
学生id | 课程id | 选修时间 |
1 | 1 | 2017-8-9 |
1 | 3 | 2017-8-9 |
1 | 4 | 2017-9-1 |
2 | 1 | 2017-8-4 |
2 | 2 | 2017-8-4 |
2 | 3 | 2017-9-1 |
3 | 3 | 2018-6-9 |
... | ... | ... |
9. 高级查询
9.1. 高级查询语法概述
一个查询语句的完整形式如下所示:
select 子句
[from 子句]
[where 子句]
[group by子句]
[having子句]
[order by子句]
[limit 子句]
;
可见,select语句还是比较复杂的——其实是mysql中最复杂的语句。
总体说明:
1,以上中括号中的任一项都可以省略,但如果不省略,就应该按该顺序出现。
2,通常,from后的子句都需要有from子句, having子句需要有group by子句。
3,这些子句的“执行顺序”,也是按此顺序进行的。
9.2. 查询结果数据及select选项
9.2.1. 查询“固定数据”
例:
select 1;
select 2, ‘abc’;
select 3, now();
9.2.2. select中可以进行计算
例:
select 1 + 2;
select 3+4*5, 6 + round(6.7) ; #其中round( )为系统函数
9.2.3. 查询出的数据字段可以使用别名
例:
select 1 as d1, 2+3 as d2;
select user_name as un, user_pass as pwd from users;
9.2.4. 使用distinct消除查询结果重复行
重复行的含义:
两行(或两行以上)的数据完全一样。
语法形式:
select disctinct 字段1, 字段2, ... from 表名;
9.3. where子句
语法形式:
select .... from 表名 where 查询条件;
说明:
1,查询条件,类似php语言中的判断条件,也就是说,where相当于if。
2,查询条件的作用是:针对from子句的表“进行一行一行筛选”,以筛选出符合条件的行。
3,查询条件中,可以使用很多的运算符,包括:算术运算符,比较运算符,逻辑运算符,等等。
示例:
where id > 10; //比较运算符
where age - 18 >= 0; //算术运算符,比较运算符
where id < 20 and age >= 18; //比较运算符,逻辑运算符
where year % 4 = 0 and year % 100 != 0 || year % 400 = 0;
//算术运算符,比较运算符,逻辑运算符
9.4. mysql运算符
9.4.1. 算术运算符
+ - * / %
9.4.2. 比较运算符:
相等: =
不相等: <> 或 !=
大于: >
大于等于: >=
小于: <
小于等于: <=
9.4.3. 逻辑运算符:
逻辑与: && 或 and
逻辑或: || 或 or
逻辑非: ! 或 not
导入范例数据表(电子商城表):
9.4.4. 其他特殊运算符
like模糊查找运算符:
用于判断某个字符型字段的值是否包含给定的字符。
语法形式:
xxx字段 like ‘%关键字%’
其中:%表示“任意个数的任意字符”。
还可以使用“_”(下杠),表示“任意一个字符”。
where name like ‘罗%’ //找出name的第一个字为“罗”的所有
//可以找出:”罗成”,“罗永浩”,“罗纳尔多”,“罗”
//但找不出“c罗纳尔多”这个
where name like ‘罗_’ //可以找出:”罗成”, “罗兰”,
//但找不出“c罗”,“罗永浩”
极端情况:
where name like “罗” //其实它只是相当于: name = ‘罗’
如果不使用“%”或“_”,则 like 相当于等于(=)。比如:
xxx字段 like ‘关键字’
相当于:
xxx字段 = ‘关键字’
between范围限定运算符:
用于判断某个字段的值是否在给定的两个数据范围之间。
语法形式:
xxx字段 between 值1 and 值2
其含义相当于: xxx字段 >= 值1 and xxx字段 <= 值2
in运算符:
用于判断某个字段的值是否在给出的若干个“可选值”范围。
语法形式:
xxx字段 in (值1, 值2, ...... )
其含义是:该字段的值等于所列出的任意一个值,就算满足条件,比如:
籍贯 in (‘北京’,‘山东’,‘河北’, ‘江西’); //则某人籍贯为上述4个之一就ok。
is运算符:
用于判断一个字段中的是“是否存在”(即有没有),只有两个写法,如下所示:
where content is null; //不能写成: content = null;
where content is not null; //不能写成: content != null;
9.5. group by子句
语法形式:
group by 字段1, 字段2, .... ;
含义:
表示对所取得的数据,以所给定的字段来进行分组。
最后的结果就是将数据分成了若干组,每组作为一个“整体”成为一行数据。
特别注意:
分组之后,只有“组信息”——一行就是一组
示例:
对于如下原始数据:
对其按“品牌”进行分组:
结果为:
特别注意:
分组查询的结果,要理解为,将“若干行原始数据”,分成了若干组,结果是每组为一行数据。
即:一行数据就代表“一组”这个集合概念,而不再是单个概念。
因此:一行中出现的信息,应该是“组的信息”,而不是“个体信息”。
于是,对于分组查询(group by),select中出现的信息,通常就只有两种情况的信息了:
- 分组本身的字段信息;
- 一组的综合统计信息,主要包括:
- 计数值: count(字段), 表示求出一组中原始数据的行数;
- 最大值: max(字段),表示求出一组中该字段的最大值;
- 最小值: min(字段),表示求出一组中该字段的最小值;
- 平均值: avg(字段),表示求出一组中该字段的平均值;
- 总和值: sum(字段),表示求出一组中该字段的累加和;
以上5个函数,也称为“聚合函数”!
示例:
多条件分组:
将product表中的所有商品以品牌和产地进行分组,并求出每一组的数量
select pinpai, chandi, count(*) as 数量 from product group by pinpai, chandi;
9.6. having子句
语法形式:
having 筛选条件
含义:
having的含义跟where的含义一样,但having是只用于对group by分组的结果进行的条件筛选。
即:having其实是相当于分组之后“有若干行数据”,然后对这些行再筛选。
示例:
查询出品牌平均价超过5000的所有品牌的平均价,最高价,以及产品的数量。
再来一个:
9.7. order by子句
语法形式:
order by 字段1 [asc或desc], 字段2 [asc或desc], ....
含义:
对前面所取得的数据按给定的字段进行排序。
排序方式有: 正序asc, 倒序desc,如果省略不写,就是asc
示例:
9.8. limit 子句
语法形式:
limit 起始行号,行数
说明:
1,limit表示对前面所取得的数据再进行数量上的筛选:取得从某行开始的多少行。
2,行号就是前面所取得数据的“自然顺序号”,从0开始算起——注意不是id,或任何其他实际数据。
3,起始行号可以省略,此时limit后只用一个数字,表示从第0行开始取出多少行。
4,limit子句通常用在“翻页”功能上,用于找出“第n页”的数据,其公式为:
limit (n - 1) * pageSize, pageSize; 其中pageSize表示每页显示的条数。
示例1:
取出商品表中价格最高的3个商品,并按倒序排列出来。
select * from product order by price desc limit 0,3;
应用:
limit子句常常用于网页的“翻页功能”。
假设总的数据行数为9,每页显示2行(条),则:
查看第1页: select * from product limit 0, 2;
查看第2页: select * from product limit 2, 2;
查看第3页: select * from product limit 4, 2;
.....
查看第n页: select * from product limit (n-1)*2, 2;
10. 高级插入
10.1. 同时插入多行记录
语句形式:
insert into 表名(字段1,字段2,...) values (值1,值2,... ), (值1, 值2,... ), ......;
10.2. 插入查询的结果数据
含义:
就是将一个select语句的查询结果,插入到某个表中!
语句形式:
insert into 表名(字段1,字段2,...) select (xx1, xx2, ... ) ... ;
要求:
1, 插入语句的字段个数,跟select语句的字段个数相等;
2, 插入语句的字段类型,跟select语句的字段类型相符;
10.3. set语法插入数据
语句形式:
insert into 表名 set 字段1=值1, 字段2=值2,.... ;
10.4. 蠕虫复制
所谓蠕虫复制,就是针对一个表的数据,进行快速的复制并插入到所需要的表中,以期在短时间内具备“大量数据”,以用于测试或其他特殊场合,比如:
1,将一个表的大量数据,复制到另一个表中;
将一个表的数据复制到本身表中以产生大量数据;
10.5. 插入时主键冲突的解决办法
所谓主键冲突是指,当插入一条记录的时候,如果插入的记录的主键值,在现有的数据中已经存在,则此时,因为主键不能重复,因此就产生了“主键冲突”。
主键冲突的演示:
现有数据:
插入一个数据(其主键已经存在的情形):
那如果出现主键冲突,该怎么办呢?
办法1:忽略
——终止插入,数据不改变,语句不报错。
其语法为:
insert ignore into 表名 ( 字段.... ) values (值.....);
办法2:替换
——删除原纪录,插入新纪录。
其语法为:
replace into 表名 ( 字段.... ) values (值.....);
说明:此replace的用法跟insert一样,也可以插入新纪录,只是如果新纪录出现主键冲突,就会删除原纪录后,再插入该新纪录。
办法3:更新
——设置为去更新原有数据(而并不插入)。
语法为:
insert into 表名 ( 字段.... ) values (值.....) on duplicate key update XX字段=新的值;
更新类似“替换”(replace),区别是:
替换:是将新的数据完整覆盖旧的数据
更新:可以预先设定需要覆盖的旧数据
11. 高级删除
11.1. 按指定顺序删除指定数量的数据
语法形式:
delete from 表名 where ... [order by 字段名, ...] [limit 数量n];
说明:
1,order by用于设定删除数据时的删除顺序,跟select语句中的order by子句道理一样。
2,limit 用于设定删除数据时要删除的行数,即删除的数据可能少于条件筛选出来的数据。
11.2. truncate清空
语法形式:
truncate 表名;
说明:
表示清空指定表中的所有数据并将表恢复到“初始状态”(就类似刚刚创建一样)。
对比:
无条件删除: delete from 表名;
结果:删除了指定表中的所有数据——但表仍然会被纪录为“已使用过”。
差别:主要是对于”auto_increment”的字段,会保留使用过的最大值,而trancate后的表,自增长的序号会完全重新开始(就像新表一样)。
12. 高级更新
语法形式:
update 表名 set 字段名1=字段值1, ... where ... [order by 字段名, ...] [limit 数量n];
说明:
1,order by用于设定更新数据时的更新顺序,跟select语句中的order by子句道理一样。
2,limit 用于设定更新数据时要更新的行数,即更新的数据量可能少于条件筛选出来的数据量。
13. 联合(union)查询
13.1. 联合查询概念
含义:
联合查询是指将2个或2个以上的字段数量相同的查询结果,“纵向堆叠”后合并为一个结果。
图示如下:
select id, f1, f2 from join1
union
select id2, c1, c2 from join2;
13.2. 联合查询语法
语法形式:
select查询1
union [all或distinct]
select查询2
union [all或distinct]
select查询3
......
[order by 字段 [asc或desc] ]
[limit 起始行号,数量] ;
说明:
1, 所有单个查询结果应该具有相等的列数。
2, 所有单个查询的列类型应该具有一致性(即每个查询的第n列的数据类型一致)。
3, 单个查询的列名可以不同,但最终的列名是第一个查询的列名(可以使用别名)。
4, union可以带all或distinct参数,如果省略就是distinct,即默认已经消除重复行了。
5, 最后的order by或limit是对整个联合之后的结果数据进行排序或数量限定。
6, order by子句中的排序字段应该使用第一个查询中的字段名,如果有别名就必须使用别名。
7, 可见,假设:
查询1有n1行,m列;
查询2有n2行,m列;
则两个表“联合”之后的结果,有最多n1+n2行,m列。
示例:
14. 连接(join)查询
连接(join)查询是将两个查询的结果以“横向对接”的方式合并起来的结果。
对比:联合查询 是将两个查询的结果以“纵向堆叠”的方式合并起来的结果。
14.1. 连接查询概述
连接查询,是将两个查询(或表)的每一行,以“两两横向对接”的方式,所得到的所有行的结果。
即一个表中的某行,跟另一个表中的某行,进行“横向对接”,而得到一个新行。
如下图所示:
则他们对接(连接)之后的结果类似这样:
可见,假设:
表1有n1行,m1列;
表2有n2行,m2列;
则表1和表2“连接”之后,就会有:
n1*n2行;
m1+m2列。
连接查询基本形式如下:
select ... from 表1 [连接方式] join 表2 [on连接条件] where ... ;
可见,连接查询只是作为from子句的“数据源”。
或者说,连接查询是扩大了数据源,从原来的一个表作为数据源,扩大为多个表作为数据源。
连接查询包括以下这些不同形式:
交叉连接,内连接,外连接(分:左外连接,右外连接)。
14.2. 交叉连接(cross join)
语法形式:
from 表1 [cross] join 表2
说明:
1,交叉连接其实可以认为是连接查询的“完全版本”,即所有行都无条件地都连接起来了。
2,关键字“cross”可以省略;
3,交叉连接又称为“笛卡尔积”,通常应用价值不大。
4,交叉连接还有一种写法: from 表1, 表2;
14.3. 内连接(inner join)
语法形式:
from 表1 [inner] join 表2 on 连接条件
说明:
1,内连接其实是交叉连接的基础上,再通过on条件而筛选出来的部分数据。
2,关键字“inner”可以省略,但建议写上。
3,内连接是应用最广泛的一种连接查询,其本质是根据条件筛选出“有意义的数据”。
演示:
找出出所有商品及其所属类别。
找出所有价格大于5000的家用电器的商品的完整信息(含所属类别);
14.4. 外连接
外连接分为左外连接和右外连接。
14.4.1. 左外连接(left join):
语法形式:
from 表1 left [outer] join 表2 on 连接条件
说明:
1,左外连接其实是保证左边表的数据都能够取出的一种连接。
2,左外连接其实是在内连接的基础上,再加上左边表中所有不能满足条件的数据
3,关键字“outer”可以省略。
演示:
找出所有类别及各类别中的商品(需列出类别名称,商品名称,价格,品牌和产地)
14.4.2. 右外连接(right join):
语法形式:
from 表1 right [outer] join 表2 on 连接条件
说明:
1,右外连接其实是保证右边表的数据都能够取出的一种连接。
2,右外连接其实是在内连接的基础上,再加上右边表中所有不能满足条件的数据。
3,关键字“outer”可以省略。
select * from join1 left join join2 on join1.f1 = join2.c1;
演示:
找出所有用户及其订单信息(需列出用户id,用户名,订单号,订单总价,订单地址)
可见:
左连接,右连接,其实是可以互换的——无非是把两个表的顺序调换一下。
14.5. 自连接
自连接不是一种新的连接形式,而只是一个表“自己跟自己连接”,这怎么做到呢?
语法形式:
from 表1 as a [连接形式] join 表1 as b on a.xx字段1=b.xx字段名
说明:
1, 自连接其实还是两个表连接,只是将一个表用不同的别名,当做两个表。
2, 自连接适用于一个表中的某个字段的值“来源于”当前表的另一个字段的情况。
示例:
地区表如下所示:
id area_name parent_id
1 北京市 0
2 河北省 0
3 山东省 0
4 石家庄 2
5 保定 2
6 衡水 2
7 济南 3
8 青岛 3
9 烟台 3
... ...
要求查询每个城市及其所在省份,结果类似如下所示:
城市 省份
石家庄 河北省
保定 河北省
思路:
select a.area_name, b.area_name from area as a join area as b on a.parent_id = b.id;
需求稍作调整:
找出所有省份及其下属城市。
15. 子查询(subquery)
15.1. 子查询的概念
子查询就是指一个“正常查询语句”中的某个部分(比如select部分,from部分, where部分)又出现了查询的一种查询形式,比如:
select * from XX表名 where price >= (一个子查询语句);
此时,子查询所在上“上层查询”,就被称为主查询。
也可以这么说:子查询是为主查询的某个部分提供某种数据的查询。
上一条语句中,括号中的子查询语句如果查出的是一个“某个数值”(比如3000),则其就相当于:
select * from XX表名 where price >=3000;
15.2. 标量子查询
含义:
标量子查询就是指子查询的结果是“单个值”(一行一列)的查询。
使用:
标量子查询通常用在where子句中,作为主查询的一个条件判断的数据。
本质上,标量子查询的结果,就可以直接当做“一个值”来使用。
找出产品表中价格大于北京产地的产品平均价的所有产品。
找出所有奢侈品!
奢侈品的定义为:其价格超过贵重品的平均价!
贵重品的定义为:超过所有商品的平均价!
15.3. 列子查询
含义:
列子查询查出的结果为“一列数据”,类似这样:
select pinpai from product where chandi = ‘北京’;
结果为:
使用:
列子查询通常用在where子句的 in 运算符中,代替in运算符中的“字面值”列表数据。
比如:
select * from product where chandi in ( '北京', '深圳','天津' )
如果in中的数据并不方便一个一个列出,但可以通过一个查询得到,就可以使用查询来实现:
select * from product where chandi in ( select chandi from product price > 4000 );
示例:
查出出产贵重商品(假设价格超过5000即为贵重商品)的那些产地的所有商品。
15.4. 行子查询
含义:
行子查询查出的结果通常是一行,类似这样:
select pinpai, chandi from product where price=11499;
结果为:
使用:
行子查询的结果通常跟“行构造符”一起,在where条件子句中做为条件数据,类似这样:
where (字段1, 字段2 ) = (行子查询)
或
where row(字段1, 字段2 ) = (行子查询) //含义跟上一行是一样的,即row可以省略
示例:
找出跟单价最高的商品同品牌同产地的所有商品。
15.5. 表子查询
含义:
当一个子查询查出的结果是“多行多列”的时候,就是表子查询。
表子查询的结果相当于一个表,可以直接当做一个表来使用。
使用:
表子查询通常用在主查询的from子句中,作为一个“数据源”。
注意:
此时需要给该子查询设置一个别名,类似这样:
from (select ... 子查询 ) as tab1
示例:
查出商品价格大于4000的所有商品的数量和均价
两个结果一样:
15.6. 有关子查询的特定关键字
15.6.1. in关键字
in关键字在子查询中主要用在列子查询中代替人为手工罗列出来的多个“字面值”数据。
举例:
找出联想品牌的商品都有哪些类别。
select * from product_type where protype_id in(
#找出联想品牌的所有商品的类别id
select distinct protype_id from product where pinpai = ‘联想’
)
15.6.2. any关键字
any关键字用在比较操作操符的后面,表示查询结果的多个数据中的任一个满足该比较操作符就算满足。
举例:
找出在北京生产的但价格比在深圳生产的任一商品贵的商品。
15.6.3. all关键字
all关键字用在比较操作操符的后面,表示查询结果的多个数据中的所有都满足该比较操作符才算满足。
举例:
找出在北京生产的但价格比在深圳生产的所有商品都贵的商品。
15.7. exists子查询
形式:
where exists ( 任何子查询 )
含义:
该子查询如果“有数据”, 则该exists()的结果为“true”, 即相当于 where true (恒真)
该子查询如果“没有数据”,则该exists()的结果为“false”,即相当于where false(恒假)
说明:
1,此子查询语句通常需要用到主查询语句中的字段作为查询条件。
示例:
1,查询商品分类名称中带“电”字的所有商品;
2,查询联想品牌的产品都有哪些分类;
特别注意:
通常,有意义exists子查询不能单独执行
对比:之前的4种子查询都可以单独执行
16. 数据管理
16.1. 数据备份
数据备份就是指将一个数据库中的数据,转存为一个或多个文件的过程。
16.1.1. 备份整个数据库
命令形式:
mysqldump.exe -h主机地址 -u用户名 -p密码 数据库名 > 备份文件名(含路径)
说明:
1, 跟登录mysql类似,密码可以不写,则随后会提示输入
2, 该语句是mysql/bin中的一个命令,不是sql语句(即不应该登录mysql后使用)
示例:
备份我们的php69数据库:
16.1.2. 备份单个表
命令形式:
mysqldump.exe -h主机地址 -u用户名 -p密码 数据库名 表名 > 备份文件名(含路径)
说明:
1, 跟登录mysql类似,密码可以不写,则随后会提示输入
2, 该语句是mysql/bin中的一个命令,不是sql语句(即不应该登录mysql后再去使用)
示例:
16.2. 数据还原(数据恢复)
数据还原(恢复)是指将一个之前备份过的数据文件,恢复(还原)到某个数据库的过程。
还原其实不分整个库还是单个表,都是一样的。
命令形式:
mysql.exe -h主机地址 -u用户名 -p密码 目标数据库名 < 想要还原的备份文件名(含路径)
示例:
17. 用户管理:
用户管理主要包括两方面的工作:
用户账号的管理,包括:创建,删除,改密
用户权限的管理,包括:授予权限,取消权限
17.1. 查看用户
mysql数据库管理系统中有个数据库叫做“mysql”,绝对不能删除!
其中有个表“user”,就是存储了当前数据库系统中的所有用户信息。
初始时只有一个用户:root 。
查看用户:
use mysql;
select * from user;
17.2. 创建用户
语法形式:
create user ‘用户名’[@’允许登录的地址’] identified by ‘密码’;
说明:
1, 创建用户之后,数据库mysql中的user表中就会多一个用户。
2, ‘允许登录的地址’,就是允许登录的客户端的ip地址,或
① ”localhost”表示只能本地登录;
② “%”表示任何位置都可以登录;
③ 该部分可以省略,如果省略,默认就是”%”;
④ 后续涉及到用户的操作,都是这个格式。
示例:
create user ‘user1’ identified by ‘123’;
create user ‘user2’@’localhost’ identified by ‘123’;
create user ‘user3’@’192.168.1.103’ identified by ‘123’;
create user ‘user4’@’%’ identified by ‘123’;
17.3. 删除用户
语法形式:
drop user 用户[@’允许登录的地址’];
删除用户后,数据库mysql中的user表中就会少一个用户。
17.4. 修改/设置用户密码
语法形式:
set password for 用户[@’允许登录的地址’] = password(‘密码’);
17.5. 授予用户权限
语法形式:
grant 操作1,操作2,.... on *.*或数据库名.* 或 数据库名.表名 to 用户[@’允许登录的地址’];
说明:
1,“操作”其实就是权限名,是一个“特定词”,比如:delete, insert, update, select, create, 等等。
① 其中,还可以用“all”,表示“所有权限”(除了grant权限)。
2,on后表示对“什么东西”来设定该权限,意思是对什么库的什么表,其中:
① *.* :表示所有库的所有表;
② 数据库名.* :表示该指定数据库的所有表;
③ 数据库名.表名:表示该指定数据库的该指定表;
示例:
mysql中的所有操作(权限),有如下所示:
17.6. 取消用户授权
语法形式:
revoke 操作1,操作2,.... on *.*或数据库名.* 或 数据库名.表名 from 用户[@’允许的地址’];
提示:
测试的时候,需要使用两个cmd窗口,一个是root用户进行用户和权限管理,另一个窗口用于测试。