30000字学完MySql数据库(安装、SQL、索引、事务等)
1. 数据库基本介绍
1.1 什么是数据库
数据库: 用于保存数据的仓库. 本质上就是一个文件系统, 只是需要访问这个文件系统需要使用特定的语句(sql)进行操作.
1.2 数据库的作用
我们开发应用程序的时候,程序中的所有数据,最后都需要保存到专业软件中。这些专业的保存数据的软件我们称为数据库。
我们学习数据库,并不是学习如何去开发一个数据库软件,我们学习的是如何使用数据库以及数据库中的数据记录的操作。而数据库软件是由第三方公司研发。
1.3 常见的数据库
数据库一般被分为两大类: 关系型 、非关系型
常见的关系型数据库软件:
-
Oracle: 是Oracle公司的大型关系型数据库, 收费的
-
DB2: IBM公司提供的数据库产品, 收费的
-
SqlServer: 微软提供的数据库产品, 收费的
-
Sybase: Sybase公司的 , 目前已经过时了, 但其数据库建模工具(PowerDesign)使用较为广泛
-
MySQL: 早期瑞典一个公司发明,后期被sun公司收购,后期被Oracle。
java 中常用的数据库产品:
MySQL(5.x) 、Oracle、DB2
1.4 什么是关系型数据库
在开发软件的时候,软件中的数据之间必然会有一定的关系存在,需要把这些数据保存在数据库中,同时也要维护数据之间的关系,这时就可以直接使用上述的那些数据库。而上述的所有数据库都属于关系型数据库。
描述数据之间的关系,并保存在数据库中,同时学习如果根据这些关系查询数据库中的数据,
关系型数据:设计数据库的时候,需要使用E-R图来描述。
E-R:实体关系图。
实体:可以理解成我们Java程序中的一个对象。在E-R图中使用 矩形(长方形) 表示。
针对一个实体中的属性,我们称为这个实体的数据,在E-R图中使用 椭圆表示。
实体和实体之间的关系:在E-R图中使用菱形表示。
ER图示:
矩形用来表示实体
椭圆用来表示实体的属性
菱形用来表示之间的关系
2. mysql如何在linux安装
2.1 vmware中安装完linux注意事项
2.1.1 防火墙的问题
service iptables stop (立即生效,重启失效)
chkconfig iptables off (重启生效,永久关闭防火墙)
2.1.2 软件安装统一的管理目录
安装包存放位置: mkdir -p /export/software
软件安装位置: mkdir -p /export/servers
数据存储的位置: mkdir -p /export/data
日志存储的位置: mkdir -p /export/logs
2.1.3 软件环境
vmware(12以上)、CRT(连接linux工具)、centos6.9
2.1.4 安装环境
1、VMware软件安装
2、构建虚拟机
3、需要配置Linux(ip,mac地址,hostname,防火墙),就可以通过crt这个客户端连接进行操作
4、在linux操作系统进行安装msyql-5.6
说明:因为在linux操作系统中,安装软件的方式主要有3种:
1、源码安装(redis)
2、rpm安装
3、yum在线安装 ---linux联网()
2.2 虚拟机中安装MySQL
-
-
检测是否自带的MySQL
rpm -qa |grep mysql
-
-
卸载自带的MySQL
rpm -e --nodeps mysql-libs-5.1.73-8.el6_8.x86_64
-
-
上传mysql的安装包
建议使用rz进行上传即可:
下载上传插件(下载一次即可): yum -y install lrzsz
使用 rz 命令上传即可或者直接拖
上传目录: /export/software
-
-
安装即可
rpm -ivh *.rpm
-
-
查看初始化密码:
安装成功后, 会产生一个随机密码, 随机密码放置的位置: /root/.mysql_secret
cat /root/.mysql_secret
-
-
启动MySQL并登陆
启动mysql服务:
service mysql start
登陆mysql:
mysql -uroot -p密码
(密码即为查看到的随机密码)
-
-
修改密码
set PASSWORD=PASSWORD('123456');
-
-
退出MySQL客户端
quit;
-
-
用新密码进行登录即可
mysql -uroot -p(新密码)
-
-
远程授权
grant all privileges on *.* to 'root' @'%' identified by '123456';
flush privileges;
-
-
验证远程授权是否成功
通过Windows的mysql连接工具连接远程linux上的mysql, 如果正常连接成功说明授权成功
3. MySQL的基础操作篇
3.1 登录与退出
登录:
mysql -uroot -p密码
退出:
quit
3.2 输入查询
-
-
查看当前mysql的版本号及当前时间
SELECT VERSION(),CURRENT_DATE();
注意:
1) SQL语句不区分大小写, 只要单词写对了, 即可查询
-
-
使用SQL 可以进行简单的运算
SELECT SIN(PI()/4), (4+1)*5;
注意:
1) PI() 表示的圆周率 3.141593
2) 计算时如果有小括号, 会先计算小括号里面的内容
3) SQL语句以分号结尾, 一个分号就代表是一句SQL的结束
select SIN(PI()/4) ; select (4+1)*5; 这是两句SQL
4) 在进行书写的时候,如果一条SQL太长, 可以分为多行书写, 只要不输入分号, 就不会认为SQL已经结束
5) 写到一半, 如果不想执行SQL了, 在SQL后面加上\c 然后回车即可
3.3 创建和使用数据库
-
-
查看当前有那些数据库
show databases ;
-
-
创建数据库
create databases 数据库名称;
-
-
使用和切换数据库
use 数据库名称 ;
3.4 创建表及使用
-
-
查看当前数据库中有那些表
show tables ;
-
-
创建一个表
create table 表名 (
字段名称(长度) 数据类型 [约束] ,
字段名称(长度) 数据类型 [约束] ,
字段名称(长度) 数据类型 [约束]
)
例如:
CREATE TABLE pet (
name VARCHAR(20),
owner VARCHAR(20),
species VARCHAR(20),
sex CHAR(1),
birth DATE,
death DATE
);
-
-
查看表的结构
show create table 表名 ;
desc 表名 ;
-
-
第一种:将以上数据整理成SQL语句,insert into pet.... -
第二种:通过加载文件的方式将数据导入到表中 -
在表中导入数据的方式有两种 -
在表创建后, 导入数据
第二种: 在本地创建一个pet.txt文件, 名称可以自定义 (注:每个字段中用tab键隔开,字段没有值得记录用\N代替)
文件的内容:
Fluffy Harold cat f 1993-02-04
Claws Gwen cat m 1994-03-17
Buffy Harold dog f 1989-05-13
Fang Benny dog m 1990-08-27
Bowser Diane dog m 1979-08-31 1995-07-29
Chirpy Gwen bird f 1998-09-11
Whistler Gwen bird \N 1997-12-09 \N
Slim Benny snake m 1996-04-29
执行加载文件的SQL将其导入表中:
load data local infile '本地路径' into table 表名 ;
范例:
load data local infile '/root/pet.txt' into table pet;
检验是否已经导入成功:
select * from 表名 ;
注意:
put -a 文件路径 //将指定文件上传的服务器.
示例: put -a D:\compile\pet.txt
rm -rf 文件名 //移除指定的文件.
示例: rm -rf test01.sql
3.5 数据查询部分
-
-
查询全部数据
select * from 表名 ;
-
-
删除表中全部数据
delete from 表名 ;
-
-
更新表中指定记录的数据
update 表名 set 字段名称1 = 值1,字段名称2 = 值2,字段名称3 = 值3 where 条件 ;
注意: 如果没有where条件, 就会对表中所有的数据进行对应修改
-
-
查询特定的行
select * from 表名 where 字段名称 = '值' ;
-
-
查询某个范围的数据
select * from 表名 where 字段名称 >|>=|<|<= 值 ;
select * from 表名 where 字段名称 between min and max ;
-
-
多条件查询: and 和 or
select * from 表名 where 条件1 and|or 条件2 and|or (条件3 and|or 条件4) ....;
and: 并列关系, 结果必须是and条件内的数据
or: 或者关系 , 结果如果有展示, 没有就不展示
如果有括号的, 优化执行括号内的数据
-
-
查询返回指定列的数据
select 字段名称1,字段名称2... from 表名 ;
-
-
如果表中有重复数据, 可以将其去重 : distinct
select distinct 字段名称1,字段名称2... from 表名 ;
-
-
排序操作: order by
SELECT *|字段列表 FROM 表名 ORDER BY 排序字段1 [排序方式],排序字段2 [排序方式];
排序方式: desc 和 asc , 默认为升序排序
如果是多个字段排序, 会先按照第一个字段进行排序,如果第一个字段有相同的, 然后在按照第二个字段排序
-
-
日期计算
查询当前的日期:
select curdate() from pet;
获取当年的年 :
select YEAR('2018-02-05') AS YEARS from pet;
获取当年的月
select month('2018-02-05') AS month from pet;
获取当年的日
select day('2018-02-05') AS day from pet;
计算年龄:
SELECT name, birth, CURDATE(), TIMESTAMPDIFF(YEAR,birth,CURDATE()) AS age FROM pet;
-
-
is null和 is not null值
SELECT name, birth, death, TIMESTAMPDIFF(YEAR,birth,death) AS age FROM pet WHERE death IS NOT NULL ORDER BY age;
格式: 字段 is null 筛选这个字段为null的数据
字段 is not null 筛选这个字段不为null的数据
4. 案例
-
-
创建表和导入数据
CREATE TABLE shop (
article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
dealer CHAR(20) DEFAULT '' NOT NULL,
price DOUBLE(16,2) DEFAULT '0.00' NOT NULL,
PRIMARY KEY(article, dealer)
);
INSERT INTO shop VALUES
(1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),
(3,'C',1.69),(3,'D',1.25),(4,'D',19.95);
-
-
检索表中的全部数据
select * from shop;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0001 | A | 3.45 |
| 0001 | B | 3.99 |
| 0002 | A | 10.99 |
| 0003 | B | 1.45 |
| 0003 | C | 1.69 |
| 0003 | D | 1.25 |
| 0004 | D | 19.95 |
+---------+--------+-------+
-
-
求某一列的最大值或者最小值
SELECT MAX(article) AS article FROM shop;
+---------+
| article |
+---------+
| 4 |
+---------+
//求某一列的最小值
select min(price) as article from shop;
+---------+
| article |
+---------+
| 1.25 |
+---------+
-
-
过滤出某个字段值最大的整条记录数据
使用子查询:
SELECT article, dealer, price FROM shop WHERE price=(SELECT MAX(price) FROM shop);
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0004 | D | 19.95 |
+---------+--------+-------+
使用自关联查询:
SELECT s1.article, s1.dealer, s1.price FROM shop s1 LEFT JOIN shop s2 ON s1.price < s2.price WHERE s2.article IS NULL;
SELECT article, dealer, price FROM shop ORDER BY price DESC LIMIT 1;
-
-
求出每一列的最大值,并且根据某一个字段进行分组--分组topn求法
SELECT article, MAX(price) AS price FROM shop GROUP BY article;
+---------+-------+
| article | price |
+---------+-------+
| 0001 | 3.99 |
| 0002 | 10.99 |
| 0003 | 1.69 |
| 0004 | 19.95 |
+---------+-------+
5. SQL中的聚合函数
SQL语言中定义了部分的函数,可以帮助我们完成对查询结果的计算操作:
-
-
count 统计个数(行数) -
-
sum函数:求和 -
-
avg函数:求平均值 -
-
max、min 求最大值和最小值
5.1 count函数
语法: select count(*|列名) from 表名;
注意:count在根据指定的列统计的时候,如果这一列中有null 不会被统计在其中。
mysql> select * from pet;
+----------+--------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+----------+--------+---------+------+------------+------------+
| Fluffy | Harold | cat | f | 1993-02-04 | NULL |
| Claws | Gwen | cat | m | 1994-03-17 | NULL |
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
| Fang | Benny | dog | m | 1990-08-27 | NULL |
| Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |
| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |
| Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |
| Slim | Benny | snake | m | 1996-04-29 | NULL |
+----------+--------+---------+------+------------+------------+
8 rows in set (0.00 sec)
mysql> select count(sex) from pet;
+------------+
| count(sex) |
+------------+
| 7 |
+------------+
1 row in set (0.00 sec)
mysql> select count(owner) from pet;
+--------------+
| count(owner) |
+--------------+
| 8 |
+--------------+
1 row in set (0.00 sec)
mysql> select count(death) from pet;
+--------------+
| count(death) |
+--------------+
| 1 |
+--------------+
5.2 sum 函数
语法: select sum(列名) from 表名;
注意事项:
1、如果使用sum 多列进行求和的时候,如果某一列中的有null,这一列所在的行中的其他数据不会被加到总和。
2、可以使用mysql 数据库提供的函数 ifnull(列名,值)
3、在数据库中定义double类型数据,是一个近似值,需要确定准确的位数,这时可以把这一列设计成numeric类型。numeric(数据的总列数,小数位数)
mysql> select sum(price) from shop;
+------------+
| sum(price) |
+------------+
| 42.77 |
+------------+
5.3 avg 函数
语法:select avg(列名) from 表名;
mysql> select avg(price) from shop;
+------------+
| avg(price) |
+------------+
| 6.110000 |
+------------+
5.4 max函数
语法:select max(列名) from 表名;
mysql> select max(price) from shop;
+------------+
| max(price) |
+------------+
| 19.95 |
+------------+
5.5 min函数
语法:select min(列名) from 表名;
mysql> select min(price) from shop;
+------------+
| min(price) |
+------------+
| 1.25 |
+------------+
6. SQL分类
6.1 DDL语句 (数据库定义语言)
对数据库 表 列 进行操作
查看数据库:show database;
创建数据库 create database 数据库名;
create database 数据库名 character set 需要使用的编码;
查询创建数据库语句:show create database 数据库名;
删除数据库 drop database 需要删除的数据库名;
查看当前正在使用的数据库 select database();
使用数据库: use 数据库名
创建表: creat table 表名(字段名 类型(长度) [约束],字段名 类型(长度) [约束]..);
查看表: show tables;
查看创建表的语句: show creat table 表名;
查看表结构: desc 表名;
删除表: drop table 表名;
向表中添加字段: alter table 表名 add 字段名 类型 [约束];
修改 对字段进行修改 但不修改字段名: alter table 表名 modify 字段名 类型 [约束];
改变 对字段进行修改 可以修改字段名: alter table 表名 change 旧字段名 新字段名 类型 [约束];
删除表中的列: alter table 表名 字段;
修改表名: rename table 旧表名 to 新表名;
6.2 DML语句(数据库操作语言)
对数据库里的数据进行操作 增 删 改
如 update, insert, delete
insert into 表名(字段名,字段名..) values(值,值,..);
insert into 表名 values(值,值,..);
update 表名 set 字段=值,字段=值..where 条件 ;
delete from 表名 where 条件 ;
truncate delete区别:
delete 删除数据时 自动增长不会清除
truncate删除数据时 清除自动增长 重写计数
6.3 DCL语句(数据库控制语言)
用于设置用户权限和控制事务语句
如 grant......
6.4 DQL语句(数据库查询语言)
对数据库进行查询
select distinct * from 表名 where 条件
group by 分组字段 having分组完接条件筛选条件
order by 排序
distinct 去掉重复
7. 数据库的备份与恢复
7.1 备份命令
在mysql的安装目录的bin目录下有mysqldump命令,可以完成对数据库的备份。
语法:mysqldump -u 用户名 -p 数据库名> 磁盘SQL文件路径
由于mysqldump命令不是sql命令,需要在dos窗口下使用。
注意:在备份数据的时候,数据库不会被删除。可以手动删除数据库。同时在恢复数据的时候,不会
自动的给我们创建数据库,仅仅只会恢复数据库中的表和表中的数据。
例如: mysqldump -uroot -p123456 test01 >/root/data/test01.sql
其中: test01是数据库的名字
7.2 恢复命令
恢复数据库,需要手动的先创建数据库:
create database heima2;
语法:mysql -u 用户名-p 导入库名< 硬盘SQL文件绝对路径
//恢复命令
mysql -uroot -p123456 itcast</root/data/menagerie.sql
8. 多表查询
8.1 笛卡尔积介绍
笛卡尔乘积是指在数学中,两个集合X和Y的笛卡尓积(Cartesian product),又称直积,表示为X × Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员
准备数据:
create table A(
A_ID int primary key auto_increment,
A_NAME varchar(20) not null
);
insert into A values(1,'apple');
insert into A values(2,'orange');
insert into A values(3,'banana');
create table B(
A_ID int primary key auto_increment,
B_PRICE double
);
insert into B values(1,2.30);
insert into B values(2,3.50);
insert into B values(4,null);
展示效果:
mysql> select * from A,B;
+------+--------+------+---------+
| A_ID | A_NAME | A_ID | B_PRICE |
+------+--------+------+---------+
| 1 | apple | 1 | 2.3 |
| 2 | orange | 1 | 2.3 |
| 3 | banana | 1 | 2.3 |
| 1 | apple | 2 | 3.5 |
| 2 | orange | 2 | 3.5 |
| 3 | banana | 2 | 3.5 |
| 1 | apple | 4 | NULL |
| 2 | orange | 4 | NULL |
| 3 | banana | 4 | NULL |
+------+--------+------+---------+
作用:笛卡尔积的数据,对程序是没有意义的,我们需要对笛卡尔积中的数据再次进行过滤。
对于多表查询操作,需要过滤出满足条件的数据,需要把多个表进行连接,连接之后需要加上过滤的条件。
8.2 内连接:
-
显示内连接:
语法: select * from 表名1 inner join 表名2 on 关联条件 ;
-
隐式内连接:
select 列名 , 列名 .... from 表名1,表名2 where 关联条件;
8.3 外连接:
-
左外连接: -
用左边表去右边表中查询对应记录,不管是否找到,都将显示左边表中全部记录。
语法:select * from 表1 left outer join 表2 on 条件;
-
右外连接: -
用右边表去左边表查询对应记录,不管是否找到,右边表全部记录都将显示。
语法:select * from 表1 right outer join 表2 on 条件;
-
全外连接 -
左外连接和右外连接的结果合并,单会去掉重复的记录。
语法: select * from a full outer join b on a.A_ID = b.A_ID;
注意: 但是mysql数据库不支持此语法。
8.4 关联子查询
子查询:把一个sql的查询结果作为另外一个查询的参数存在。
-
-
in和exist关键词的用法
关联子查询其他的关键字使用:
回忆:age=23 or age=24 等价于 age in (23,24)
in 表示条件应该是在多个列值中。
in:使用在where后面,经常表示是一个列表中的数据,只要被查询的数据在这个列表中存在即可。
mysql> select * from A where A_ID in(1,2,3);
+------+--------+
| A_ID | A_NAME |
+------+--------+
| 1 | apple |
| 2 | orange |
| 3 | banana |
+------+--------+
3 rows in set (0.00 sec)
mysql> select * from A where A_ID =1 or A_ID =2 or A_ID =3;
+------+--------+
| A_ID | A_NAME |
+------+--------+
| 1 | apple |
| 2 | orange |
| 3 | banana |
+------+--------+
//not in
mysql> select * from A where A_ID not in (1,2,3,4);
Empty set (0.00 sec)
mysql> select * from A where A_ID not in (3,4);
+------+--------+
| A_ID | A_NAME |
+------+--------+
| 1 | apple |
| 2 | orange |
+------+--------+
2 rows in set (0.00 sec)
exists:表示存在,当子查询的结果存在,就会显示主查询中的所有数据。
mysql> select * from A where exists(select A_ID from B);
+------+--------+
| A_ID | A_NAME |
+------+--------+
| 1 | apple |
| 2 | orange |
| 3 | banana |
+------+--------+
mysql> select * from A where not exists(select A_ID from B);
Empty set (0.00 sec)
-
union 和union all使用法
UNION 语句:用于将不同表中相同列中查询的数据展示出来;(不包括重复数据)
UNION ALL 语句:用于将不同表中相同列中查询的数据展示出来;(包括重复数据)
mysql> select * from A union select * from B;
+------+--------+
| A_ID | A_NAME |
+------+--------+
| 1 | apple |
| 2 | orange |
| 3 | banana |
| 1 | 2.3 |
| 2 | 3.5 |
| 4 | NULL |
+------+--------+
6 rows in set (0.00 sec)
mysql> select * from A union all select * from B;
+------+--------+
| A_ID | A_NAME |
+------+--------+
| 1 | apple |
| 2 | orange |
| 3 | banana |
| 1 | 2.3 |
| 2 | 3.5 |
| 4 | NULL |
+------+--------+
-
case when 语句
case when 语句语法结构:
CASE sex
WHEN '1' THEN '男'
WHEN '2' THEN '女'
ELSE '其他' END
准备数据:
//创建表
create table employee(
empid int ,
deptid int ,
sex varchar(20) ,
salary double
);
//加载数据
1 10 female 5500.0
2 10 male 4500.0
3 20 female 1900.0
4 20 male 4800.0
5 40 female 6500.0
6 40 female 14500.0
7 40 male 44500.0
8 50 male 6500.0
9 50 male 7500.0
load data local infile '/root/data/emp.txt' into table employee ;
select *,
case
when salary < 5000 then "低等收入"
when salary>= 5000 and salary < 10000 then "中等收入"
when salary > 10000 then "高等收入"
end as level,
case sex
when "female" then 1
when "male" then 0
end as flag
from employee;
如下代码为宠物表的代码:
9. mysql数据类型
MySQL中定义数据字段的类型对你数据库的优化是非常重要的。
MySQL支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。
9.1 数值类型
MySQL支持所有标准SQL数值数据类型。
这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似数值数据类型(FLOAT、REAL和DOUBLE PRECISION)。
关键字INT是INTEGER的.同义词,关键字DEC是DECIMAL的同义词。
BIT数据类型保存位字段值,并且支持MyISAM、MEMORY、InnoDB和BDB表。
作为SQL标准的扩展,MySQL也支持整数类型TINYINT、MEDIUMINT和BIGINT。下面的表显示了需要的每个整数类型的存储和范围。
类型 | 大小 | 范围(有符号) | 范围(无符号) | 用途 |
---|---|---|---|---|
TINYINT | 1 字节 | (-128,127) | (0,255) | 小整数值 |
SMALLINT | 2 字节 | (-32 768,32 767) | (0,65 535) | 大整数值 |
MEDIUMINT | 3 字节 | (-8 388 608,8 388 607) | (0,16 777 215) | 大整数值 |
INT或INTEGER | 4 字节 | (-2 147 483 648,2 147 483 647) | (0,4 294 967 295) | 大整数值 |
BIGINT | 8 字节 | (-9 233 372 036 854 775 808,9 223 372 036 854 775 807) | (0,18 446 744 073 709 551 615) | 极大整数值 |
FLOAT | 4 字节 | (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) | 0,(1.175 494 351 E-38,3.402 823 466 E+38) | 单精度浮点数值 |
DOUBLE | 8 字节 | (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 双精度浮点数值 |
DECIMAL | 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 | 依赖于M和D的值 | 依赖于M和D的值 | 小数值 |
M表示: 总的数据个数, D表示: 小数点后的精确位数.
DECIMAL(5, 2), 希望获得的数字一共有5位, 并要求小数点保留两位.
11123.54321 --> 11123.54
9.2 日期和时间类型
表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。
每个时间类型有一个有效值范围和一个"零"值,当指定不合法的MySQL不能表示的值时使用"零"值。
TIMESTAMP类型有专有的自动更新特性,将在后面描述。
类型 | 大小(字节) | 范围 | 格式 | 用途 |
---|---|---|---|---|
DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 |
TIME | 3 | '-838:59:59'/'838:59:59' | HH:MM:SS | 时间值或持续时间 |
YEAR | 1 | 1901/2155 | YYYY | 年份值 |
DATETIME | 8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值 |
TIMESTAMP | 4 | 1970-01-01 00:00:00/2038结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 | YYYYMMDD HHMMSS | 混合日期和时间值,时间戳 |
9.3 字符串类型
字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。该节描述了这些类型如何工作以及如何在查询中使用这些类型。
类型 | 大小 | 用途 |
---|---|---|
CHAR | 0-255字节 | 定长字符串 |
VARCHAR | 0-65535 字节 | 变长字符串 |
TINYBLOB | 0-255字节 | 不超过 255 个字符的二进制字符串 |
TINYTEXT | 0-255字节 | 短文本字符串 |
BLOB | 0-65 535字节 | 二进制形式的长文本数据 |
TEXT | 0-65 535字节 | 长文本数据 |
MEDIUMBLOB | 0-16 777 215字节 | 二进制形式的中等长度文本数据 |
MEDIUMTEXT | 0-16 777 215字节 | 中等长度文本数据 |
LONGBLOB | 0-4 294 967 295字节 | 二进制形式的极大文本数据 |
LONGTEXT | 0-4 294 967 295字节 | 极大文本数据 |
CHAR 和 VARCHAR 类型类似,但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。
BINARY 和 VARBINARY 类似于 CHAR 和 VARCHAR,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于列值字节的数值值。
BLOB 是一个二进制大对象,可以容纳可变数量的数据。有 4 种 BLOB 类型:TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。它们区别在于可容纳存储范围不同。
有 4 种 TEXT 类型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。对应的这 4 种 BLOB 类型,可存储的最大长度不同,可根据实际情况选择。
MySQL 5.0 以上的版本:
1、一个汉字占多少长度与编码有关:
UTF-8:一个汉字=3个字节
GBK:一个汉字=2个字节
2、varchar(n) 表示 n 个字符,无论汉字和英文,Mysql 都能存入 n 个字符,仅是实际字节长度有所区别
3、MySQL 检查长度,可用 SQL 语言来查看:
select LENGTH(fieldname) from tablename
1、整型
MySQL数据类型 | 含义(有符号) |
---|---|
tinyint(m) | 1个字节 范围(-128~127) |
smallint(m) | 2个字节 范围(-32768~32767) |
mediumint(m) | 3个字节 范围(-8388608~8388607) |
int(m) | 4个字节 范围(-2147483648~2147483647) |
bigint(m) | 8个字节 范围(+-9.22*10的18次方) |
取值范围如果加了 unsigned,则最大值翻倍,如 tinyint unsigned 的取值范围为(0~256)。
int(m) 里的 m 是表示 SELECT 查询结果集中的显示宽度,并不影响实际的取值范围,没有影响到显示的宽度,不知道这个 m 有什么用。
2、浮点型(float 和 double)
MySQL数据类型 | 含义 |
---|---|
float(m,d) | 单精度浮点型 8位精度(4字节) m总个数,d小数位 |
double(m,d) | 双精度浮点型 16位精度(8字节) m总个数,d小数位 |
设一个字段定义为 float(5,3),如果插入一个数 123.45678,实际数据库里存的是 123.457,但总个数还以实际为准,即 6 位。
3、定点数
浮点型在数据库中存放的是近似值,而定点类型在数据库中存放的是精确值。
decimal(m,d) 参数 m<65 是总个数,d<30 且 d<m 是小数位。
m: 表示总个数, 要求最大值64.
d: 表示小数位数,
d<30; 小数位数最多保留: 29个.
4、字符串(char,varchar,_text)
MySQL数据类型 | 含义 |
---|---|
char(n) | 固定长度,最多255个字符 |
varchar(n) | 固定长度,最多65535个字符 |
tinytext | 可变长度,最多255个字符 |
text | 可变长度,最多65535个字符 |
mediumtext | 可变长度,最多2的24次方-1个字符 |
longtext | 可变长度,最多2的32次方-1个字符 |
char 和 varchar:
-
-
char(n) 若存入字符数小于n,则以空格补于其后,查询之时再将空格去掉。所以 char 类型存储的字符串末尾不能有空格,varchar 不限于此。 -
-
char(n) 固定长度,char(4) 不管是存入几个字符,都将占用 4 个字节,varchar 是存入的实际字符数 +1 个字节(n<=255)或2个字节(n>255),所以 varchar(4),存入 3 个字符将占用 4 个字节。 -
-
char 类型的字符串检索速度要比 varchar 类型的快。
varchar 和 text:
-
-
varchar( 可指定 n,text 不能指定,内部存储 varchar 是存入的实际字符数 +1 个字节(n<=255)或 2 个字节(n>255),text 是实际字符数 +2 个字节。 -
-
text 类型不能有默认值。 -
-
varchar 可直接创建索引,text 创建索引要指定前多少个字符。varchar 查询速度快于 text, 在都创建索引的情况下,text 的索引似乎不起作用。 -
总结: 效率: char > varchar > text.
5.二进制数据(Blob)
-
-
BLOB和text存储方式不同,TEXT以文本方式存储,英文存储区分大小写,而Blob是以二进制方式存储,不分大小写。 -
-
BLOB存储的数据只能整体读出。 -
-
TEXT可以指定字符集,BLOB不用指定字符集。
6.日期时间类型
MySQL数据类型 | 含义 |
---|---|
date | 日期 '2008-12-2' |
time | 时间 '12:25:36' |
datetime | 日期时间 '2008-12-2 22:06:44' |
timestamp | 自动存储记录修改时间 |
若定义一个字段为timestamp,这个字段里的时间数据会随其他字段修改的时候自动刷新,所以这个数据类型的字段可以存放这条记录最后被修改的时间。
数据类型的属性
MySQL关键字 | 含义 |
---|---|
NULL | 数据列可包含NULL值 |
NOT NULL | 数据列不允许包含NULL值 |
DEFAULT | 默认值 |
PRIMARY KEY | 主键 |
AUTO_INCREMENT | 自动递增,适用于整数类型 |
UNSIGNED | 无符号 |
CHARACTER SET name | 指定一个字符集 |
charset
10. MySQL GROUP BY 语句
GROUP BY 语句根据一个或多个列对结果集进行分组。
在分组的列上我们可以使用 COUNT, SUM, AVG,等函数。
语法结构:
SELECT column_name, function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name;
准备数据:
CREATE TABLE `employee_tbl` (
`id` int(11) NOT NULL,
`name` char(10) NOT NULL DEFAULT '',
`date` datetime NOT NULL,
`singin` tinyint(4) NOT NULL DEFAULT '0' COMMENT '登录次数',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
INSERT INTO `employee_tbl` VALUES ('1', '小明', '2016-04-22 15:25:33', '1'), ('2', '小王', '2016-04-20 15:25:47', '3'), ('3', '小丽', '2016-04-19 15:26:02', '2'), ('4', '小王', '2016-04-07 15:26:14', '4'), ('5', '小明', '2016-04-11 15:26:40', '4'), ('6', '小明', '2016-04-04 15:26:54', '2');
mysql> SELECT name, COUNT(*) FROM employee_tbl GROUP BY name;
+--------+----------+
| name | COUNT(*) |
+--------+----------+
| 小丽 | 1 |
| 小明 | 3 |
| 小王 | 2 |
+--------+----------+
mysql> select * from employee_tbl;
+----+------+---------------------+--------+
| id | name | date | singin |
+----+------+---------------------+--------+
| 1 | ?? | 2016-04-22 15:25:33 | 1 |
| 2 | ?? | 2016-04-20 15:25:47 | 3 |
| 3 | ?? | 2016-04-19 15:26:02 | 2 |
| 4 | ?? | 2016-04-07 15:26:14 | 4 |
| 5 | ?? | 2016-04-11 15:26:40 | 4 |
| 6 | ?? | 2016-04-04 15:26:54 | 2 |
+----+------+---------------------+--------+
mysql> select * from employee_tbl group by singin;
+----+------+---------------------+--------+
| id | name | date | singin |
+----+------+---------------------+--------+
| 1 | ?? | 2016-04-22 15:25:33 | 1 |
| 3 | ?? | 2016-04-19 15:26:02 | 2 |
| 2 | ?? | 2016-04-20 15:25:47 | 3 |
| 4 | ?? | 2016-04-07 15:26:14 | 4 |
+----+------+---------------------+--------+
注意:
1、group by 可以实现一个最简单的去重查询,假设想看下有哪些员工,除了用 distinct,还可以用:
SELECT name FROM employee_tbl GROUP BY name;
返回的结果集就是所有员工的名字。
2、分组后的条件使用 HAVING 来限定,WHERE 是对原始数据进行条件限制。几个关键字的使用顺序为 where 、group by 、having、order by ,例如:
SELECT name ,sum(singin) FROM employee_tbl WHERE date>'2015-04-07 15:26:14' GROUP BY name HAVING sum(*)>5 ORDER BY sum(singin) DESC;
11、MySQL LIKE 子句
我们知道在 MySQL 中使用 SQL SELECT 命令来读取数据, 同时我们可以在 SELECT 语句中使用 WHERE 子句来获取指定的记录。
WHERE 子句中可以使用等号 = 来设定获取数据的条件,如 "company = 'itcast"。
但是有时候我们需要获取 company 字段含有 "it" 字符的所有记录,这时我们就需要在 WHERE 子句中使用 SQL LIKE 子句。
SQL LIKE 子句中使用百分号 %字符来表示任意字符。
如果没有使用百分号 %, LIKE 子句与等号 = 的效果是一样的。
语法:
以下是 SQL SELECT 语句使用 LIKE 子句从数据表中读取数据的通用语法:
SELECT field1, field2,...fieldN
FROM table_name
WHERE field1 LIKE condition1 [AND|OR] filed2 = 'somevalue'
-
你可以在 WHERE 子句中指定任何条件。 -
你可以在 WHERE 子句中使用LIKE子句。 -
你可以使用LIKE子句代替等号 =。 -
LIKE 通常与 ' % 和 _ ' 一同使用,类似于一个字符的模糊搜索。 -
你可以使用 AND 或者 OR 指定一个或多个条件。 -
你可以在 DELETE 或 UPDATE 命令中使用 WHERE...LIKE 子句来指定条件。
mysql> select * from pet where species like '%d%';
+----------+--------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+----------+--------+---------+------+------------+------------+
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
| Fang | Benny | dog | m | 1990-08-27 | NULL |
| Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |
| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |
| Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |
+----------+--------+---------+------+------------+------------+
12. MySQL NULL 值处理
我们已经知道 MySQL 使用 SQL SELECT 命令及 WHERE 子句来读取数据表中的数据,但是当提供的查询条件字段为 NULL 时,该命令可能就无法正常工作。
为了处理这种情况,MySQL提供了三大运算符:
-
IS NULL: 当列的值是 NULL,此运算符返回 true。 -
IS NOT NULL: 当列的值不为 NULL, 运算符返回 true。 -
<=>: 比较操作符(不同于=运算符),当比较的的两个值为 NULL 时返回 true。
关于 NULL 的条件比较运算是比较特殊的。你不能使用 = NULL 或 != NULL 在列中查找 NULL 值 。
在 MySQL 中,NULL 值与任何其它值的比较(即使是 NULL)永远返回 false,即 NULL = NULL 返回false 。
MySQL 中处理 NULL 使用 IS NULL 和 IS NOT NULL 运算符。
13. MySQL 元数据
你可能想知道MySQL以下三种信息:
-
查询结果信息: SELECT, UPDATE 或 DELETE语句影响的记录数。 -
数据库和数据表的信息: 包含了数据库及数据表的结构信息。 -
MySQL服务器信息: 包含了数据库服务器的当前状态,版本号等。
在MySQL的命令提示符中,我们可以很容易的获取以上服务器信息。
命令 | 描述 |
---|---|
SELECT VERSION( ) | 服务器版本信息 |
SELECT DATABASE( ) | 当前数据库名 (或者返回空) |
SELECT USER( ) | 当前用户名 |
SHOW STATUS | 服务器状态 |
SHOW VARIABLES | 服务器配置变量 |
14 MySQL 函数
MySQL 有很多内置的函数,以下列出了这些函数的说明。
14.1 MySQL 字符串函数
函数 | 描述 | 实例 |
---|---|---|
ASCII(s) | 返回字符串 s 的第一个字符的 ASCII 码。 | 返回 CustomerName 字段第一个字母的 ASCII 码:SELECT ASCII(CustomerName) AS NumCodeOfFirstCharFROM Customers; |
CHAR_LENGTH(s) | 返回字符串 s 的字符数 | 返回字符串 itcast 的字符数SELECT CHAR_LENGTH("itcast") AS LengthOfString; |
CHARACTER_LENGTH(s) | 返回字符串 s 的字符数 | 返回字符串 itcast 的字符数SELECT CHARACTER_LENGTH("itcast") AS LengthOfString; |
CONCAT(s1,s2...sn) | 字符串 s1,s2 等多个字符串合并为一个字符串 | 合并多个字符串SELECT CONCAT("SQL ", "itcast ", "Gooogle ", "Facebook") AS ConcatenatedString; |
CONCAT_WS(x, s1,s2...sn) | 同 CONCAT(s1,s2,...) 函数,但是每个字符串直接要加上 x,x 可以是分隔符 | 合并多个字符串,并添加分隔符:SELECT CONCAT_WS("-", "SQL", "Tutorial", "is", "fun!")AS ConcatenatedString; |
FIELD(s,s1,s2...) | 返回第一个字符串 s 在字符串列表(s1,s2...)中的位置 | 返回字符串 c 在列表值中的位置:SELECT FIELD("c", "a", "b", "c", "d", "e"); |
FIND_IN_SET(s1,s2) | 返回在字符串s2中与s1匹配的字符串的位置 | 返回字符串 c 在指定字符串中的位置:SELECT FIND_IN_SET("c", "a,b,c,d,e"); |
FORMAT(x,n) | 函数可以将数字 x 进行格式化 "#,###.##", 将 x 保留到小数点后 n 位,最后一位四舍五入。 | 格式化数字 "#,###.##" 形式:SELECT FORMAT(250500.5634, 2); -- 输出 250,500.56 |
INSERT(s1,x,len,s2) | 字符串 s2 替换 s1 的 x 位置开始长度为 len 的字符串 | 从字符串第一个位置开始的 6 个字符替换为 itcast:SELECT INSERT("google.com", 1, 6, "runnob"); -- 输出:itcast.com |
LOCATE(s1,s) | 从字符串 s 中获取 s1 的开始位置 | 获取 b 在字符串 abc 中的位置:SELECT INSTR('abc','b') -- 2 |
LCASE(s) | 将字符串 s 的所有字母变成小写字母 | 字符串 itcast 转换为小写:SELECT LOWER('itcast') -- itcast |
LEFT(s,n) | 返回字符串 s 的前 n 个字符 | 返回字符串 itcast 中的前两个字符:SELECT LEFT('itcast',2) -- it |
LEFT(s,n) | 返回字符串 s 的前 n 个字符 | 返回字符串 abcde 的前两个字符:SELECT LEFT('abcde',2) -- ab |
LOCATE(s1,s) | 从字符串 s 中获取 s1 的开始位置 | 返回字符串 abc 中 b 的位置:SELECT LOCATE('b', 'abc') -- 2 |
LOWER(s) | 将字符串 s 的所有字母变成小写字母 | 字符串 itcast 转换为小写:SELECT LOWER('itcast') -- itcast |
LPAD(s1,len,s2) | 在字符串 s1 的开始处填充字符串 s2,使字符串长度达到 len | 将字符串 xx 填充到 abc 字符串的开始处:SELECT LPAD('abc',5,'xx') -- xxabc |
LTRIM(s) | 去掉字符串 s 开始处的空格 | 去掉字符串 itcast开始处的空格:SELECT LTRIM(" itcast") AS LeftTrimmedString;-- itcast |
MID(s,n,len) | 从字符串 s 的 start 位置截取长度为 length 的子字符串,同 SUBSTRING(s,n,len) | 从字符串 itcast 中的第 2 个位置截取 3个 字符:SELECT MID("itcast", 2, 3) AS ExtractString; -- UNO |
POSITION(s1 IN s) | 从字符串 s 中获取 s1 的开始位置 | 返回字符串 abc 中 b 的位置:SELECT POSITION('b' in 'abc') -- 2 |
REPEAT(s,n) | 将字符串 s 重复 n 次 | 将字符串 itcast 重复三次:SELECT REPEAT('itcast',3) -- itcastitcastitcast |
REPLACE(s,s1,s2) | 将字符串 s2 替代字符串 s 中的字符串 s1 | 将字符串 abc 中的字符 a 替换为字符 x:SELECT REPLACE('abc','a','x') --xbc |
REVERSE(s) | 将字符串s的顺序反过来 | 将字符串 abc 的顺序反过来:SELECT REVERSE('abc') -- cba |
RIGHT(s,n) | 返回字符串 s 的后 n 个字符 | 返回字符串 itcast 的后两个字符:SELECT RIGHT('itcast',2) -- ob |
RPAD(s1,len,s2) | 在字符串 s1 的结尾处添加字符串 s1,使字符串的长度达到 len | 将字符串 xx 填充到 abc 字符串的结尾处:SELECT RPAD('abc',5,'xx') -- abcxx |
RTRIM(s) | 去掉字符串 s 结尾处的空格 | 去掉字符串 itcast 的末尾空格:SELECT RTRIM("itcast ") AS RightTrimmedString; -- itcast |
SPACE(n) | 返回 n 个空格 | 返回 10 个空格:SELECT SPACE(10); |
STRCMP(s1,s2) | 比较字符串 s1 和 s2,如果 s1 与 s2 相等返回 0 ,如果 s1>s2 返回 1,如果 s1<s2 返回 -1 | 比较字符串:SELECT STRCMP("itcast", "itcast"); -- 0 |
SUBSTR(s, start, length) | 从字符串 s 的 start 位置截取长度为 length 的子字符串 | 从字符串 itcast 中的第 2 个位置截取 3个 字符:SELECT SUBSTR("itcast", 2, 3) AS ExtractString; -- UNO |
SUBSTRING(s, start, length) | 从字符串 s 的 start 位置截取长度为 length 的子字符串 | 从字符串 itcast 中的第 2 个位置截取 3个 字符:SELECT SUBSTRING("itcast", 2, 3) AS ExtractString; -- UNO |
SUBSTRING_INDEX(s, delimiter, number) | 返回从字符串 s 的第 number 个出现的分隔符 delimiter 之后的子串。如果 number 是正数,返回第 number 个字符左边的字符串。如果 number 是负数,返回第(number 的绝对值(从右边数))个字符右边的字符串。 | SELECT SUBSTRING_INDEX('a*b','*',1) -- aSELECT SUBSTRING_INDEX('a*b','*',-1) -- bSELECT SUBSTRING_INDEX(SUBSTRING_INDEX('a*b*c*d*e','*',3),'*',-1) -- c |
TRIM(s) | 去掉字符串 s 开始和结尾处的空格 | 去掉字符串 itcast 的首尾空格:SELECT TRIM(' itcast ') AS TrimmedString; |
UCASE(s) | 将字符串转换为大写 | 将字符串 itcast 转换为大写:SELECT UCASE("itcast"); -- itcast |
UPPER(s) | 将字符串转换为大写 | 将字符串 itcast 转换为大写:SELECT UPPER("itcast"); -- itcast |
14.2 MySQL 数字函数
函数名 | 描述 | 实例 |
---|---|---|
ABS(x) | 返回 x 的绝对值 | 返回 -1 的绝对值:SELECT ABS(-1) -- 返回1 |
ACOS(x) | 求 x 的反余弦值(参数是弧度) | SELECT ACOS(0.25); |
ASIN(x) | 求反正弦值(参数是弧度) | SELECT ASIN(0.25); |
ATAN(x) | 求反正切值(参数是弧度) | SELECT ATAN(2.5); |
ATAN2(n, m) | 求反正切值(参数是弧度) | SELECT ATAN2(-0.8, 2); |
AVG(expression) | 返回一个表达式的平均值,expression 是一个字段 | 返回 Products 表中Price 字段的平均值:SELECT AVG(Price) AS AveragePrice FROM Products; |
CEIL(x) | 返回大于或等于 x 的最小整数 | SELECT CEIL(1.5) -- 返回2 |
CEILING(x) | 返回大于或等于 x 的最小整数 | SELECT CEILING(1.5) -- 返回2 |
COS(x) | 求余弦值(参数是弧度) | SELECT COS(2); |
COT(x) | 求余切值(参数是弧度) | SELECT COT(6); |
COUNT(expression) | 返回查询的记录总数,expression 参数是一个字段或者 * 号 | 返回 Products 表中 products 字段总共有多少条记录:SELECT COUNT(ProductID) AS NumberOfProducts FROM Products; |
DEGREES(x) | 将弧度转换为角度 | SELECT DEGREES(3.1415926535898) -- 180 |
n DIV m | 整除,n 为被除数,m 为除数 | 计算 10 除于 5:SELECT 10 DIV 5; -- 2 |
EXP(x) | 返回 e 的 x 次方 | 计算 e 的三次方:SELECT EXP(3) -- 20.085536923188 |
FLOOR(x) | 返回小于或等于 x 的最大整数 | 小于或等于 1.5 的整数:SELECT FLOOR(1.5) -- 返回1 |
GREATEST(expr1, expr2, expr3, ...) | 返回列表中的最大值 | 返回以下数字列表中的最大值:SELECT GREATEST(3, 12, 34, 8, 25); -- 34 返回以下字符串列表中的最大值:SELECT GREATEST("Google", "itcast", "Apple"); -- itcast |
LEAST(expr1, expr2, expr3, ...) | 返回列表中的最小值 | 返回以下数字列表中的最小值:SELECT LEAST(3, 12, 34, 8, 25); -- 3 返回以下字符串列表中的最小值:SELECT LEAST("Google", "itcast", "Apple"); -- Apple |
LN | 返回数字的自然对数 | 返回 2 的自然对数:SELECT LN(2); -- 0.6931471805599453 |
LOG(x) | 返回自然对数(以 e 为底的对数) | SELECT LOG(20.085536923188) -- 3 |
LOG10(x) | 返回以 10 为底的对数 | SELECT LOG10(100) -- 2 |
LOG2(x) | 返回以 2 为底的对数 | 返回以 2 为底 6 的对数:SELECT LOG2(6); -- 2.584962500721156 |
MAX(expression) | 返回字段 expression 中的最大值 | 返回数据表 Products 中字段 Price 的最大值:SELECT MAX(Price) AS LargestPrice FROM Products; |
MIN(expression) | 返回字段 expression 中的最小值 | 返回数据表 Products 中字段 Price 的最小值:SELECT MIN(Price) AS LargestPrice FROM Products; |
MOD(x,y) | 返回 x 除以 y 以后的余数 | 5 除于 2 的余数:SELECT MOD(5,2) -- 1 |
PI() | 返回圆周率(3.141593) | SELECT PI() --3.141593 |
POW(x,y) | 返回 x 的 y 次方 | 2 的 3 次方:SELECT POW(2,3) -- 8 |
POWER(x,y) | 返回 x 的 y 次方 | 2 的 3 次方:SELECT POWER(2,3) -- 8 |
RADIANS(x) | 将角度转换为弧度 | 180 度转换为弧度:SELECT RADIANS(180) -- 3.1415926535898 |
RAND() | 返回 0 到 1 的随机数 | SELECT RAND() --0.93099315644334 |
ROUND(x) | 返回离 x 最近的整数 | SELECT ROUND(1.23456) --1 |
SIGN(x) | 返回 x 的符号,x 是负数、0、正数分别返回 -1、0 和 1 | SELECT SIGN(-10) -- (-1) |
SIN(x) | 求正弦值(参数是弧度) | SELECT SIN(RADIANS(30)) -- 0.5 |
SQRT(x) | 返回x的平方根 | 25 的平方根:SELECT SQRT(25) -- 5 |
SUM(expression) | 返回指定字段的总和 | 计算 OrderDetails 表中字段 Quantity 的总和:SELECT SUM(Quantity) AS TotalItemsOrdered FROM OrderDetails; |
TAN(x) | 求正切值(参数是弧度) | SELECT TAN(1.75); -- -5.52037992250933 |
TRUNCATE(x,y) | 返回数值 x 保留到小数点后 y 位的值(与 ROUND 最大的区别是不会进行四舍五入) | SELECT TRUNCATE(1.23456,3) -- 1.234 |
14.3 MySQL 日期函数
函数名 | 描述 | 实例 |
---|---|---|
ADDDATE(d,n) | 计算其实日期 d 加上 n 天的日期 | SELECT ADDDATE("2017-06-15", INTERVAL 10 DAY);->2017-06-25 |
ADDTIME(t,n) | 时间 t 加上 n 秒的时间 | SELECT ADDTIME('2011-11-11 11:11:11', 5)->2011-11-11 11:11:16 (秒) |
CURDATE() | 返回当前日期 | SELECT CURDATE();-> 2018-09-19 |
CURRENT_DATE() | 返回当前日期 | SELECT CURRENT_DATE();-> 2018-09-19 |
CURRENT_TIME | 返回当前时间 | SELECT CURRENT_TIME();-> 19:59:02 |
CURRENT_TIMESTAMP() | 返回当前日期和时间 | SELECT CURRENT_TIMESTAMP()-> 2018-09-19 20:57:43 |
CURTIME() | 返回当前时间 | SELECT CURTIME();-> 19:59:02 |
DATE() | 从日期或日期时间表达式中提取日期值 | SELECT DATE("2017-06-15"); -> 2017-06-15 |
DATEDIFF(d1,d2) | 计算日期 d1->d2 之间相隔的天数 | SELECT DATEDIFF('2001-01-01','2001-02-02')-> -32 |
DATE_ADD(d,INTERVAL expr type) | 计算起始日期 d 加上一个时间段后的日期 | SELECT ADDDATE('2011-11-11 11:11:11',1)-> 2011-11-12 11:11:11 (默认是天)SELECT ADDDATE('2011-11-11 11:11:11', INTERVAL 5 MINUTE)-> 2011-11-11 11:16:11 (TYPE的取值与上面那个列出来的函数类似) |
DATE_FORMAT(d,f) | 按表达式 f的要求显示日期 d | SELECT DATE_FORMAT('2011-11-11 11:11:11','%Y-%m-%d %r')-> 2011-11-11 11:11:11 AM |
DATE_SUB(date,INTERVAL expr type) | 函数从日期减去指定的时间间隔。 | Orders 表中 OrderDate 字段减去 2 天:SELECT OrderId,DATE_SUB(OrderDate,INTERVAL 2 DAY) AS OrderPayDateFROM Orders |
DAY(d) | 返回日期值 d 的日期部分 | SELECT DAY("2017-06-15"); -> 15 |
DAYNAME(d) | 返回日期 d 是星期几,如 Monday,Tuesday | SELECT DAYNAME('2011-11-11 11:11:11')->Friday |
DAYOFMONTH(d) | 计算日期 d 是本月的第几天 | SELECT DAYOFMONTH('2011-11-11 11:11:11')->11 |
DAYOFWEEK(d) | 日期 d 今天是星期几,1 星期日,2 星期一,以此类推 | SELECT DAYOFWEEK('2011-11-11 11:11:11')->6 |
DAYOFYEAR(d) | 计算日期 d 是本年的第几天 | SELECT DAYOFYEAR('2011-11-11 11:11:11')->315 |
EXTRACT(type FROM d) | 从日期 d 中获取指定的值,type 指定返回的值。type可取值为:MICROSECONDSECONDMINUTEHOURDAYWEEKMONTHQUARTERYEARSECOND_MICROSECONDMINUTE_MICROSECONDMINUTE_SECONDHOUR_MICROSECONDHOUR_SECONDHOUR_MINUTEDAY_MICROSECONDDAY_SECONDDAY_MINUTEDAY_HOURYEAR_MONTH | SELECT EXTRACT(MINUTE FROM '2011-11-11 11:11:11') -> 11 |
ROM_DAYS(n) | 计算从 0000 年 1 月 1 日开始 n 天后的日期 | SELECT FROM_DAYS(1111)-> 0003-01-16 |
HOUR(t) | 返回 t 中的小时值 | SELECT HOUR('1:2:3')-> 1 |
LAST_DAY(d) | 返回给给定日期的那一月份的最后一天 | SELECT LAST_DAY("2017-06-20");-> 2017-06-30 |
LOCALTIME() | 返回当前日期和时间 | SELECT LOCALTIME()-> 2018-09-19 20:57:43 |
LOCALTIMESTAMP() | 返回当前日期和时间 | SELECT LOCALTIMESTAMP()-> 2018-09-19 20:57:43 |
MAKEDATE(year, day-of-year) | 基于给定参数年份 year 和所在年中的天数序号 day-of-year 返回一个日期 | SELECT MAKEDATE(2017, 3);-> 2017-01-03 |
MAKETIME(hour, minute, second) | 组合时间,参数分别为小时、分钟、秒 | SELECT MAKETIME(11, 35, 4);-> 11:35:04 |
MICROSECOND(date) | 返回日期参数所对应的毫秒数 | SELECT MICROSECOND("2017-06-20 09:34:00.000023");-> 23 |
MINUTE(t) | 返回 t 中的分钟值 | SELECT MINUTE('1:2:3')-> 2 |
MONTHNAME(d) | 返回日期当中的月份名称,如 Janyary | SELECT MONTHNAME('2011-11-11 11:11:11')-> November |
MONTH(d) | 返回日期d中的月份值,1 到 12 | SELECT MONTH('2011-11-11 11:11:11')->11 |
NOW() | 返回当前日期和时间 | SELECT NOW()-> 2018-09-19 20:57:43 |
PERIOD_ADD(period, number) | 为 年-月 组合日期添加一个时段 | SELECT PERIOD_ADD(201703, 5); -> 201708 |
PERIOD_DIFF(period1, period2) | 返回两个时段之间的月份差值 | SELECT PERIOD_DIFF(201710, 201703);-> 7 |
QUARTER(d) | 返回日期d是第几季节,返回 1 到 4 | SELECT QUARTER('2011-11-11 11:11:11')-> 4 |
SECOND(t) | 返回 t 中的秒钟值 | SELECT SECOND('1:2:3')-> 3 |
SEC_TO_TIME(s) | 将以秒为单位的时间 s 转换为时分秒的格式 | SELECT SEC_TO_TIME(4320)-> 01:12:00 |
STR_TO_DATE(string, format_mask) | 将字符串转变为日期 | SELECT STR_TO_DATE("August 10 2017", "%M %d %Y");-> 2017-08-10 |
SUBDATE(d,n) | 日期 d 减去 n 天后的日期 | SELECT SUBDATE('2011-11-11 11:11:11', 1)->2011-11-10 11:11:11 (默认是天) |
SUBTIME(t,n) | 时间 t 减去 n 秒的时间 | SELECT SUBTIME('2011-11-11 11:11:11', 5)->2011-11-11 11:11:06 (秒) |
SYSDATE() | 返回当前日期和时间 | SELECT SYSDATE()-> 2018-09-19 20:57:43 |
TIME(expression) | 提取传入表达式的时间部分 | SELECT TIME("19:30:10");-> 19:30:10 |
TIME_FORMAT(t,f) | 按表达式 f 的要求显示时间 t | SELECT TIME_FORMAT('11:11:11','%r')11:11:11 AM |
TIME_TO_SEC(t) | 将时间 t 转换为秒 | SELECT TIME_TO_SEC('1:12:00')-> 4320 |
TIMEDIFF(time1, time2) | 计算时间差值 | SELECT TIMEDIFF("13:10:11", "13:10:10");-> 00:00:01 |
TIMESTAMP(expression, interval) | 单个参数时,函数返回日期或日期时间表达式;有2个参数时,将参数加和 | SELECT TIMESTAMP("2017-07-23", "13:10:11");-> 2017-07-23 13:10:11 |
TO_DAYS(d) | 计算日期 d 距离 0000 年 1 月 1 日的天数 | SELECT TO_DAYS('0001-01-01 01:01:01')-> 366 |
WEEK(d) | 计算日期 d 是本年的第几个星期,范围是 0 到 53 | SELECT WEEK('2011-11-11 11:11:11')-> 45 |
WEEKDAY(d) | 日期 d 是星期几,0 表示星期一,1 表示星期二 | SELECT WEEKDAY("2017-06-15");-> 3 |
WEEKOFYEAR(d) | 计算日期 d 是本年的第几个星期,范围是 0 到 53 | SELECT WEEKOFYEAR('2011-11-11 11:11:11')-> 45 |
YEAR(d) | 返回年份 | SELECT YEAR("2017-06-15");-> 2017 |
YEARWEEK(date, mode) | 返回年份及第几周(0到53),mode 中 0 表示周天,1表示周一,以此类推 | SELECT YEARWEEK("2017-06-15");-> 201724 |
14.4 MySQL 高级函数
函数名 | 描述 | 实例 |
---|---|---|
BIN(x) | 返回 x 的二进制编码 | 15 的 2 进制编码:SELECT BIN(15); -- 1111 |
BINARY(s) | 将字符串 s 转换为二进制字符串 | SELECT BINARY "itcast";-> itcast |
CASE expression WHEN condition1 THEN result1 WHEN condition2 THEN result2 ... WHEN conditionN THEN resultN ELSE resultEND |
CASE 表示函数开始,END 表示函数结束。如果 condition1 成立,则返回 result1, 如果 condition2 成立,则返回 result2,当全部不成立则返回 result,而当有一个成立之后,后面的就不执行了。 | SELECT CASE WHEN 1 > 0 THEN '1 > 0' WHEN 2 > 0 THEN '2 > 0' ELSE '3 > 0' END->1 > 0 |
CAST(x AS type) | 转换数据类型 | 字符串日期转换为日期:SELECT CAST("2017-08-29" AS DATE);-> 2017-08-29 |
COALESCE(expr1, expr2, ...., expr_n) | 返回参数中的第一个非空表达式(从左向右) | SELECT COALESCE(NULL, NULL, NULL, 'itcast.com', NULL, 'google.com');-> itcast.com |
CONNECTION_ID() | 返回服务器的连接数 | SELECT CONNECTION_ID();-> 4292835 |
CONV(x,f1,f2) | 返回 f1 进制数变成 f2 进制数 | SELECT CONV(15, 10, 2);-> 1111 |
CONVERT(s USING cs) | 函数将字符串 s 的字符集变成 cs | SELECT CHARSET('ABC')->utf-8 SELECT CHARSET(CONVERT('ABC' USING gbk))->gbk |
CURRENT_USER() | 返回当前用户 | SELECT CURRENT_USER();-> guest@% |
DATABASE() | 返回当前数据库名 | SELECT DATABASE(); -> itcast |
IF(expr,v1,v2) | 如果表达式 expr 成立,返回结果 v1;否则,返回结果 v2。 | SELECT IF(1 > 0,'正确','错误') ->正确 |
IFNULL(v1,v2) | 如果 v1 的值不为 NULL,则返回 v1,否则返回 v2。 | SELECT IFNULL(null,'Hello Word')->Hello Word |
ISNULL(expression) | 判断表达式是否为空 | SELECT ISNULL(NULL);->1 |
LAST_INSERT_ID() | 返回最近生成的 AUTO_INCREMENT 值 | SELECT LAST_INSERT_ID();->6 |
NULLIF(expr1, expr2) | 比较两个字符串,如果字符串 expr1 与 expr2 相等 返回 NULL,否则返回 expr1 | SELECT NULLIF(25, 25);-> |
SESSION_USER() | 返回当前用户 | SELECT SESSION_USER();-> guest@% |
SYSTEM_USER() | 返回当前用户 | SELECT SYSTEM_USER();-> guest@% |
USER() | 返回当前用户 | SELECT USER();-> guest@% |
VERSION() | 返回数据库的版本号 | SELECT VERSION()-> 5.6.34 |
15. MySQL 索引
MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。
索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。
创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。
实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。
上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。
建立索引会占用磁盘空间的索引文件。
15.1 普通索引
-
这是最基本的索引,它没有任何限制。它有以下几种创建方式:
-
创建索引:
格式: CREATE INDEX indexName ON mytable(username(length));
//创建索引
create index id on B(A_ID);
如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length。
-
-
修改表结构(添加索引)
格式: ALTER table tableName ADD INDEX indexName(columnName)
-
-
创建表的时候直接指定
CREATE TABLE mytable(
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
INDEX [indexName] (username(length))
);
-
-
删除索引的语法
DROP INDEX [indexName] ON mytable;
15.2 唯一索引
它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:
-
-
创建索引
CREATE UNIQUE INDEX indexName ON mytable(username(length))
-
-
修改表结构
ALTER table mytable ADD UNIQUE [indexName] (username(length))
-
-
创建表的时候直接指定
CREATE TABLE mytable(
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
UNIQUE [indexName] (username(length))
);
15.3 使用alter命令添加和删除索引
有四种方式来添加数据表的索引:
-
ALTER TABLE tbl_name ADD PRIMARY KEY (column_list): 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL。 -
ALTER TABLE tbl_name ADD UNIQUE index_name (column_list): 这条语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)。 -
ALTER TABLE tbl_name ADD INDEX index_name (column_list): 添加普通索引,索引值可出现多次。 -
**ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list):**该语句指定了索引为 FULLTEXT ,用于全文索引。
以下实例为在表中添加索引。
mysql> ALTER TABLE testalter_tbl ADD INDEX (c);
你还可以在 ALTER 命令中使用 DROP 子句来删除索引。尝试以下实例删除索引:
mysql> ALTER TABLE testalter_tbl DROP INDEX c;
15.4 使用alter命令添加和删除主键
主键只能在一个表中添加一个,添加主键索引时,你需要确保该主键默认不为空(NOT NULL)。实例如下:
mysql> ALTER TABLE testalter_tbl ADD PRIMARY KEY (itcast);
你也可以使用 ALTER 命令删除主键:
mysql> ALTER TABLE testalter_tbl DROP PRIMARY KEY;
删除主键时只需指定PRIMARY KEY,但在删除索引时,你必须知道索引名。
15.5 显示索引信息
你可以使用 SHOW INDEX 命令来列出表中的相关的索引信息。可以通过添加 \G 来格式化输出信息。
尝试以下实例:
格式: SHOW INDEX FROM table_name; \G
mysql> show index from B;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| B | 0 | PRIMARY | 1 | A_ID | A | 3 | NULL | NULL | | BTREE | | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
16. MySQL 事务
MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!
-
在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。 -
事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。 -
事务用来管理 insert,update,delete 语句
一般来说,事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。
-
原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,在中间某个环节不会结束。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。 -
一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。 -
隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。 -
持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
16.1 事务控制语句:
-
BEGIN或START TRANSACTION;显式地开启一个事务; -
COMMIT;也可以使用COMMIT WORK,不过二者是等价的。COMMIT会提交事务,并使已对数据库进行的所有修改成为永久性的; -
ROLLBACK;有可以使用ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改; -
SAVEPOINT identifier;SAVEPOINT允许在事务中创建一个保存点,一个事务中可以有多个SAVEPOINT; -
RELEASE SAVEPOINT identifier;删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常; -
ROLLBACK TO identifier;把事务回滚到标记点; -
SET TRANSACTION;用来设置事务的隔离级别。InnoDB存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。
16.2 MYSQL 事务处理主要有两种方法:
1、用 BEGIN, ROLLBACK, COMMIT来实现
-
BEGIN 开始一个事务 -
ROLLBACK 事务回滚 -
COMMIT 事务确认
2、直接用 SET 来改变 MySQL 的自动提交模式:
-
SET AUTOCOMMIT=0 禁止自动提交 -
SET AUTOCOMMIT=1 开启自动提交
16.3、事务并发操作出现几种问题
所谓事务,是用户定义的一个数据库操作序列,是数据库环境中的逻辑工作单元,是一个不可分割的整体。
事务的这个4个特性简称为ACID特性,事务ACID特性可能遭到破坏的因素有:
①多个事务并发执行,不同事务的操作交叉执行;
②事务在运行过程中被强行终止。
如何保证在多个事务并发执行的过程中不发生上述的两种情况,是数据库管理系统并发控制的主要责任。
16.4、丢失修改数据
举例:银行卡有100元,事务A取10元,事务B取10元,事务AB两人同时取钱,初始值都是100
16.4.1、读“脏”数据
数据库技术中,如果正常提交的事务A使用了事务B未提交的撤销数据,这种数据成为“脏数据”,会造成数据的脏读和污读。
16.4.2、不一致分析
造成这种数据不一致的主要原因是并发执行的两个事务中,一个事务在读取数据时,另一个事务正在修改同一个数据。这样就可能导致两个事务的相互干扰及“读”事务的错误执行结果。
16.5、数据库并发的控制(了解部分)
16.5.1、并发调度的可串行化
可串行化准则:多个事务的并发执行时正确的,当且仅当其结果按某一次序串行执行它们时的结果相同,这种调度策略称为可串行化调度。可串行化是并发事务正确性的准则,一个给定的并发调度,当且仅当它是可串行化的,才认为是正确的。
16.5.2、封锁
封锁是实现并发控制的非常重要的技术。封锁是指某事务在对某数据对象进行操作以前,先请求系统对其加锁,成功加锁之后该事务就对该数据对象有了控制权,只有该事务对其进行解锁之后,其他的事务才能更新它,DBMS有两种锁:
① 排它锁(也称作X锁) :可读可写
如果事务T在对某个数据对象实施了X锁,那么其他的事务必须要等到T事务接触对该数据对象的X锁之后,才能对这个数据进行加锁。
② 共享锁(也称作S锁) :只能进行读取工作
如果事务T在对某个数据对象实施了S锁,那么其他的事务也能对该数据对象实施S锁,但是对这个数据对象施加的所有S锁都释放之前不允许任何事务对该数据对象实施X锁。
16.5.3、死锁
封锁技术可以避免一些并发操作引起的不一致错误,但也会产生其他的一些问题,活锁和死锁。
① 活锁
如果某个事务处在永远等待的状态,得不到封锁的机会,这种现象为活锁,避免这种锁最好的方法就是采用先来先服务的策略。
② 死锁
两个或两个以上的事务都处于等待状态每个事务都在等待对方事务接触封锁,它才能继续执行下去,这样任何事务都处于等待状态而无法继续执行的现象称为死锁
解决死锁问题方法有两类:
A、 死锁的预防
B、 死锁的诊断与预防
17. 数据库编码
-
-
查看mysql编码
mysql> show variables like 'character%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
-
s2) 设置mysql编码
# vi /etc/my.cnf
如下(少补):
[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
sql_mode='NO_ENGINE_SUBSTITUTION'
[mysql]
default-character-set=utf8
重启mysql
# service mysql restart
再次查看编码:
# mysql -uroot -p
mysql> show variables like 'character%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)
18. mysql 的目录及配置文件
-
-
/etc/my.cnf : 这是mysql的主配置文件 -
-
/var/lib/mysql : mysql中数据库及其数据存储的目录 -
-
/var/log/mysql(或者直接在/var/lib/mysql) : 数据库的日志输出存放位置 -
-
查看端口。netstat -nltp 看是否能找到3306的端口
19. 数据库常用术语
19.1 数据模型
数据模型(Data model)是数据库结构的基础,是用来描述数据的一组概念和定义,数据模型主要有三个要素:数据结构、数据操作、数据约束条件。
数据结构:对象类型的集合,是对静态属性的描述。
数据操作:是对数据库中的各种对象性数据,允许执行的操作的集合,如增删改查等;数据操作是对系统动态热性的描述。
数据的约束条件:是一组完整性规则的集合,也就是说,对于具体的应用必须先遵循特定的语义约束条件。比如:性别只能取 “男”或者“女”中的之一。考试成绩:(满分100)只能是0-100的数值。
19.2 数据库
数据库(database)是长期存储在计算机外存上有结构,可共享的数据集合;数据库中的数据按照一定的数据模型描述、组织和存储,具有较小的冗余度,较高的数据独立性和可扩展性,并可以为多个用户共享。
常见数据库分类:
关系型数据库:如:MySQL,oracle,sqlserver
非关系型数据库:如:redis,hbase等
19.3 数据库管理系统
数据库管理系统(database managerment system, DBMS)是指数据库系统中对数据库进行管理的软件系统,是数据库系统的核心组成部分。数据库的一切操作,如增删改查以及各种控制,都是通过DBMS进行的。
具有以下4个基本的功能:
-
1、数据定义功能
用户可以通过DBMS提供的数据定义语言对数据库的数据进行定义。
-
2、数据操纵功能
用户可以通过数据操纵语言实现对数据库的增删改查操作
-
3、数据库运行管理
管理数据库的运行是DBMS运行时的核心工作。所有访问数据库的操作都要在DBMS的统一管理下进行,以保证数据的安全性、完整性、一致性以及多用户对数据库的并发使用。
-
4、数据库的建立和维护
建立数据库,包括数据库初始数据的输入与数据转换等。维护数据库,包括数据库的转储与恢复,数据库的重组织,性能监控和分析。
19.4 数据库系统相关管理人员
数据库系统的相关人员是数据库系统的重要组成部分,具体可以分为以下的三类人员
-
1、数据库管理员(DBA)
职责:负责数据库的建立、使用、维护的专门人员
-
2、应用程序开发人员
职责:开发数据库应用程序的人员,可以使用数据库管理系统的所有功能。
-
3、最终用户
职责:一般来说,是通过应用程序使用数据库的人员,最终用户无需自己编写应用程序。
19.5 数据库系统
数据库系统(database system DBS)是由硬件系统,数据库管理系统,数据库,数据库应用程序,数据库系统相关人员构成的人-机系统,是指有数据库的整个计算机系统。
说明:在许多场合下,数据库,数据库管理系统,数据库系统不做严格区分;
20 数据库设计流程
一般对于整个数据库的设置分为5大部分
-
-
明确用户需求,到底做什么? -
需求分析: -
-
优点: -
简洁明了, 描述了各个之间的逻辑关系 -
独立于计算机与具体的RDBMS无关。 -
该阶段是整个数据库设计的关键,它通过对用户需求进行综合、归纳与抽象。主要是通过E-R图表示
E-R模型的基本元素:
A、实体(Entity) 如:学生
B、属性(attribute)如:姓名
C、键码(key)如:身份证号码;
D、关系(relationship)如:两个实体之间的关系
a) 一对一(1:1): 一个人一个身份证号码;一个学校一个校长
b) 一对多(1:n):学校和老师的关系
c) 多对多(n:n):学生选课,一个学生可以选择多门课程,一门课程课被多名学生进行选修。 -
概念模型设计: -
-
与具体的数据库相关,反映出业务部门的需求 -
规范化处理,尽可能的消除关系操作过程中的异常情况。 -
逻辑模型设计: 该阶段会涉及到更多的概念,方法,理论。 -
-
创建数据库,定义数据库结构,组织数据入库,调试数据库并进行数据库的试运行。 -
数据库实施: -
-
数据库正式运行之后,对数据库运行过程中对其进行评价,调整,修改,调优等。 -
数据库的运行和维护:
21 数据库设计遵循的原则
21.1 范式概念
概念:范式就是符合某一规范级别的关系模式的集合。共有7种范式:
1NF ⊃2NF⊃3NF⊃BCNF⊃4NF⊃5NF⊃6NF
21.2 第一范式(First Normal Form)
如果一个关系模式R的所有属性都是不可分割的基本数据项,则这个关系属于第一范式。
Student(s_no,s_name,s_dept,s_location,s_course_name,s_grade)
注:1NF是关系模式应具备的最起码的条件,如果数据库设计不能满足第一范式,就不能称作是关系模式;关系数据库设计研究的关系规范化是在1NF基础之上进行的。
21.3 第二范式(Second Normal Form)
定义:若关系模式R属于第一范式,且每个非主属性都是完全函数依赖于主键,则R属于第二范式。
说明:从2NF的定义可以看出,从2NF开始讨论的是主键和非主属性之间的函数依赖关系,所以分析关系模式是属于2NF,首先指明关系模式的主键,然后在讨论非主属性和主键之间的函数依赖关系。
例如:选课关系模式
SC(s_no,c_no,score)中,主键为(s_no,c_no),而非主属性score与主键之间不存在部分函数依赖关系,所以关系模式SC属于2NF
21.4 第三范式(Third Normal Form)
定义:若关系模式R属于第一范式,且每个非主属性都不传递函数依赖于主键,则R属于第三范式。
说明:3NF说明的是非主属性和主键之间的函数依赖关系
例如:选课关系模式
SC(s_no,c_no,score)中,由于除了主键之外,只有一个非主属性score,所以score不可能构成与主键之间的传递函数依赖,所以SC属于3NF