- 数据库简介
- 关系型数据库
- MySQL安装和使用
- SQL语言
一、数据库简介
(一)数据库的发展
- 文件系统:磁盘文件存储数据
- 第一代数据库:网状模型、层次模型
- 第二代数据库:关系型数据库、结构化查询语言
- 新一代数据库:“对象—关系”型数据库
(二)文件管理系统的缺点
- 编写应用程序不方便
- 数据冗余不可避免
- 应用程序依赖性
- 不支持对文件的并发访问
- 数据间联系弱
- 难以按用户视图表示数据
- 无安全控制功能
(三)数据库管理系统的优点
- 相互关联的数据的集合
- 较少的数据冗余
- 程序与数据相互独立
- 保证数据的安全、可靠
- 最大限度地保证数据的正确性
- 数据可以并发使用并能同时保证一致性
(四)数据库管理系统的基本概念
(一)术语定义
- 数据库:数据的汇集,它以一定的组织形式存于存储介质上
- DBMS(数据库管理系统):管理数据库的系统软件,它实现数据库系统的各种功能,是数据库系统的核心
- DBA(数据库管理员):负责数据库的规划、设计、协调、维护和管理等工作
- 应用程序:指以数据库为基础的应用程序
(二)DBMS的基本功能
- 数据定义
- 数据处理:增、删、改、查
- 数据安全
- 数据备份
(三)数据库系统的架构
- 单机架构
- 大型主机/终端架构
- 主从式架构(C/S)
- 分布式架构
二、关系型数据库
(一)基本概念
- 关系:关系就是二维表,表中的行、列次序并不重要
- 行 (row):表中的每一行,又称为一条记录
- 列 (column):表中的每一列,又称为属性、字段
- 主键 (Primary key):用于惟一确定一个记录的字段
- 域 (domain):属性的取值范围
(二)主流关系型数据库
MySQL, MariaDB, PostgreSQL, Oracle, MSSQL, DB2
(三)事务: transaction
- 定义:被视作整体对待的若干个操作
- 事务的特性:ACID
A:原子性,一个事务不可分割。
当一个事务进行过程中出现了中断,下一次开始本事务时会执行回滚(rollback)操作恢复至事务执行前的状态;当一个事务完成后,会执行提交(commit)操作,此后无法再恢复至事务执行前的状态
C:一致性,数据保持一致
I:隔离性,使用锁机制避免多用户同时修改某数据,可能出现死锁
D:持久性,提交后的改变是不可撤销的,而尚未提交的数据是脏数据
(四)实体—联系模型(E-R模型)
-
实体(Entity):客观存在并可以相互区分的客观事物或抽象事件
- 在E-R图中用矩形框表示实体,把实体名写在框内
- 属性:实体所具有的特征或性质
-
联系(Relationship):数据之间的关联集合,是客观存在的应用语义链
- 实体内部的联系:指组成实体的各属性之间的联系。
- 实体之间的联系:指不同实体之间联系。
- 实体之间的联系用菱形框表示
-
实体之间联系的类型:
- 一对一联系 (1:1)
- 一对多联系 (1:n)
- 多对多联系 (m:n)
(五)数据的三要素
-
数据结构,包含两类
- 与数据类型、内容、性质有关的对象
- 与数据之间联系有关的对象
-
数据的操作
- 数据提取:在数据集合中提取感兴趣的内容(SELECT)
- 数据更新:变更数据库中的数据(INSERT、DELETE、UPDATE)
-
数据的约束条件:是一组完整性规则的集合
- 实体(行)完整性 (Entity integrity)
- 域(列)完整性 (Domain Integrity)
- 参考完整性 (Referential Integrity)
(六)范式(NF)
定义:设计关系数据库时,为设计出合理的关系型数据库而遵从的规范要求
各种范式呈递次规范,越高的范式数据库冗余越小目前有六种范式,设计关系型数据库时一般需满足至第三范式的要求
1NF:无重复的列,每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。除去同类型的字段,就是无重复的列
2NF:属性完全依赖于主键,第二范式必须先满足第一范式,要求表中的每个行必须可以被唯一地区分。通常为表加上一个列,以存储各个实例的唯一标识PK。非PK的字段需要与整个PK有直接相关性
3NF:属性不依赖于其他非主属性,满足第三范式必须先满足第二范式。第三范式要求一个数据库表中不包含已在其它表中包含的非主关键字信息,非PK的字段间不能有从属关系
有时出于性能或其他特殊需求的考虑,需要主动违反范式
(七)SQL概念
(1)基本概念:
SQL(Structure Query Language):结构化查询语言
应用编程接口
ODBC:Open Database Connectivity
JDBC:Java Data Base Connectivity索引:将表中的一个或多个字段中的数据复制一份另存,并且此些需要按特定次序排序存储
关系运算:
选择:挑选出符合条件的行
投影:挑选出需要的字段
连接:表间字段的关联
(2)约束
约束(constraint):表中的数据要遵守的限制
主键:一个或多个字段的组合(复合主键),填入的数据必须能在本表中唯一标识本行;必须提供数据,即NOT NULL,一个表只能存在一个
惟一键:一个或多个字段的组合,填入的数据必须能在本表中唯一标识本行;允许为NULL,一个表可以存在多个
外键:一个表中的某字段可填入的数据取决于另一个表的主键或唯一键已有的数据
检查:字段值在一定范围内
(3)数据模型
- 数据抽象
- 物理层:决定数据的存储格式,即RDBMS在磁盘上如何组织文件
- 逻辑层:描述存储什么数据,以及数据间存在什么样的关系
- 视图层:描述DB中的部分数据,是虚拟的表
- 关系模型的分类
- 关系模型
- 基于对象的关系模型
- 半结构化的关系模型:XML数据
三、MySQL安装和使用
(一)MySQL和MariaDB
- MariaDB是MySQL的分支,软件使用与MySQL相同
- yum安装:CentOS 6 默认安装MySQL,CentOS 7默认安装MariaDB
(1)MariaDB的特性
- 单进程,多线程
- 插件式存储引擎:
- 存储引擎有多种实现版本,功能和特性可能均略有差别,用户可根据需要灵活选择
- 主要存储引擎:MyISAM和InnoDB,当前绝大多数使用的是InnoDB(支持事务功能)
(2)MariaDB的程序组成:C/S架构
Client:mysql, mysqldump, mysqladmin
Server:mysqld_safe, mysqld, mysqld_multi
(3)服务器监听的两种socket地址
- ip socket:监听在tcp的3306端口,支持远程通信
- unix sock:监听在sock文件上(客户机路径:/tmp/mysql.sock, 服务器路径:/var/lib/mysql/mysql.sock),仅支持本机通信
当本机通信时(server: localhost, 127.0.0.1),自动使用unix sock
(二)MariaDB安装
(1)安装方式
源代码:编译安装
二进制格式的程序包:展开至特定路径,并经过简单配置后即可使用
程序包管理器管理的程序包
项目官方生成yum仓库配置信息的地址:https://downloads.mariadb.org/mariadb/repositories/
(2)yum安装和配置MariaDB
- 第1步,安装和开启服务
yum groupinstall mariadb mariadb-client
systemctl start mariadb
systemctl enable mariadb
-
第2步,提高安全性
- 安装并启动服务后,发现输入
mysql
命令后可以不需输入密码直接进入系统 - 执行
select user();
命令,发现以root@localhost登录
- 执行
select user,host,password from mysql.user;
命令,发现当前的所有用户都没有设置密码,同时允许匿名登录数据库,存在很大安全隐患
-
执行脚本
mysql_secure_installation
修改数据库安全设置- 设置数据库管理员root口令
- 禁止root远程登录
- 删除anonymous用户帐号
- 删除test数据库
再次尝试登录时,发现已经无法匿名登录了,执行
mysql -u root -p
以root@localhost身份输入争取密码后成功登录
- 安装并启动服务后,发现输入
- 第3步,编辑配置文件
/etc/my.cnf
vim /etc/my.cnf
skip-networking=1 //[mysqld]下添加选项,跳过反向解析过程加速启动
(3)通用二进制格式安装MariaDB
第1步,创建用户并制定数据库数据的存放目录
useradd -r -m -d /app/dbdata -s /sbin/nologin mysql
第2步,准备二进制程序,要求必须解压到/usr/local目录下并命名为mysql
tar xvf mariadb-10.2.8-linux-x86_64.tar.gz -C /usr/local/
cd /usr/local
ln -sv mariadb-10.2.8-linux-x86_64/ mysql //创建软链接便于切换版本
chown -R root:mysql /usr/local/mysql/
- 第3步,准备配置文件
配置文件查找次序:后面覆盖前面的配置文件
/etc/my.cnf --> /etc/mysql/my.cnf --> --default-extra-file=/PATH/TO/CONF_FILE --> ~/.my.cnf
mkdir /etc/mysql/
cp /usr/local/mysql/support-files/my-large.cnf /etc/mysql/my.cnf //复制模板文件
vim /etc/mysql/my.cnf //[mysqld]下添加三个选项
datadir = /app/dbdata //数据库数据存放目录
innodb_file_per_table= on //innodb引擎下创建的每个表都是一个文件
skip_name_resolve= on //禁止主机名解析
- 第4步,创建数据库文件
cd /usr/local/mysql
./scripts/mysql_install_db --datadir=/app/dbdata --user=mysql
- 第5步,准备日志文件
//CentOS 7下的操作
mkdir /var/log/mariadb
touch /var/log/mariadb/mariadb.log
setfacl -R -m u:mysql:rwx /var/log/mariadb/mariadb.log
//CentOS 6下的操作
touch /var/log/mysqld.log
setfacl -R -m u:mysql:rwx /var/log/mysqld.log
- 第6步,准备服务脚本,并启动服务
cp /usr/local/mysql/support-files/mysql.server /etc/rc.d/init.d/mysqld
chkconfig --add mysqld
chkconfig mysqld on
service mysqld start
- 第7步,创建环境变量
vim /etc/profile.d/mysql.sh
export PATH=/usr/local/mysql/bin:$PATH
source /etc/profile.d/mysql.sh
- 第8步,安全初始化
执行脚本:mysql_secure_installation
(三)MariaDB的使用
(1)客户端工具
mysql:命令行交互式客户端工具
mysql选项:
-u:用户名,默认为root
-h:服务器主机,默认为localhost
-p:建议使用用户密码,默认为空密码-
mysql用户账号由两部分组成:
USERNAME@HOST
HOST用于限制此用户可通过哪些远程主机连接mysql服务
支持使用通配符:- % 匹配任意长度的任意字符,如:
172.16.0.0/16
或172.16.%.%
- _ 匹配任意单个字符
- % 匹配任意长度的任意字符,如:
(2)常用命令
- 运行
mysql
命令:默认空密码登录
mysql>select user(); //查看当前用户
mysql>use mysql; //选择进入名为mysql的数据库
mysql>SELECT user,host,password FROM user;
//从当前数据库名为user的表中查询每行中user,host,password列的数据
安全初始化
/usr/local/mysql/bin/mysql_secure_installation
登录系统:
mysql -uroot -p
-u 指定用户名 -p 指定输入密码(直接跟密码时与p之间无空格)客户端命令:本地执行
mysql> help
:查询mysql客户端命令
每个命令都完整形式和简写格式
mysql> status 或\s
服务端命令:通过mysql协议发往服务器执行并取回结果
每个命令都必须有结束符号,默认为分号
select version();
四、SQL语言
(一)SQL语言简介
(1)SQL语句构成
由关键词(Keyword)组成子句(Clause),多条子句组成一条语句
SELECT * //SELECT子句,SELECT为关键词
FROM products //FROM子句,FROM为关键词
WHERE price>400 //WHERE子句,WHERE为关键词
(2)SQL语句分类
- DDL: Data Defination Language 数据定义语言
CREATE, DROP, ALTER - DML: Data Manipulation Language 数据操作语言
INSERT, DELETE, UPDATE - DCL:Data Control Language 数据控制语言
GRANT, REVOKE - DQL:Data Query Language 数据查询语言
SELECT
(3)SQL语言规范
- 大小写:
- 关键词不区分大小写(建议用大写)
- 但字符串常量区分大小写
- 跨行:
- 可单行或多行书写,每条语句以";"结尾
- 关键词不能跨多行或简写
- 用空格和缩进来提高语句的可读性
- 子句通常位于独立行,便于编辑,提高可读性
- 注释:
- SQL标准:
/*注释内容*/
多行注释
-- 注释内容
单行注释,注意有空格 - MySQL注释:
#注释内容
- SQL标准:
(4)数据库对象的命名规则
- 必须以字母开头
- 可包括数字和三个特殊字符(# _ $,不建议使用)
- 不要使用MySQL的保留字
- 同一个表下的对象不能同名
(5)数据库操作
创建数据库:
CREATE DATABASE|SCHEMA [IF NOT EXISTS] 'DB_NAME';
删除数据库:
DROP DATABASE|SCHEMA [IF EXISTS] 'DB_NAME';
查看支持所有字符集:
SHOW CHARACTER SET;
查看支持所有排序规则:
SHOW COLLATION;
获取命令使用帮助:
HELP KEYWORD;
查看数据库列表:
SHOW DATABASES;
(二)SQL语言应用
(1)创建、删除表操作
-
语法:
- 创建表:
CREATE TABLE [IF NOT EXISTS] 'tbl_name' (col1 type1 修饰符, col2 type2 修饰符, ...)
- 删除表:
DROP TABLE [IF EXISTS] tbl_name;
- 创建表:
-
修饰符
- NULL:数据列可包含NULL值
- NOT NULL:数据列不允许包含NULL值
- DEFAULT:默认值
- PRIMARY KEY:主键
- UNIQUE KEY:唯一键
- CHARACTER SET name:指定一个字符集
- AUTO_INCREMENT:自动递增,适用于整数类型
- UNSIGNED:无符号,适用于数值类型
-
其他与表相关的操作
- 查看所有的引擎:
SHOW ENGINES;
- 查看表:
SHOW TABLES [FROM db_name];
- 查看表结构:
DESC [db_name.]tbl_name;
- 查看表创建命令:
SHOW CREATE TABLE tbl_name;
- 查看表状态:
SHOW TABLE STATUS LIKE 'tbl_name'\G
\G竖直显示
- 查看所有的引擎:
(2)数据类型
-
mysql支持的数据类型:
- 数值类型
- 日期/时间类型
- 字符串(字符)类型
-
选择正确的数据类型对于获得高性能至关重要,三大原则:
- 更小的通常更好,尽量使用可正确存储数据的最小数据类型
- 简单就好,简单数据类型的操作通常需要更少的CPU周期
- 尽量避免NULL,包含为NULL的列,对MySQL更难优化
-
整型
- tinyint(m):1个字节范围
- smallint(m):2个字节范围
- mediumint(m):3个字节范围
- int(m):4个字节范围
- bigint(m):8个字节范围
- 加unsigned后缀代表正整数,取值范围:0至原范围最大值*2
- m指select查询结果显示宽度,不影响实际取值
-
浮点型,近似值
- float(m,d):单精度浮点型8位精度(4字节) m:总位数,d:小数位位数
- double(m,d):双精度浮点型16位精度(8字节) m:总位数,d:小数位位数
-
定点型,精确值
- decimal(m,d):m为总位数,d为小数位位数
- 占用空间大、计算消耗大,尽量只在精确计算时使用
-
字符串型
- char(n)固定长度,最多255个字符
- varchar(n)可变长度,最多65535个字符
- tinytext可变长度,最多255个字符
- text可变长度,最多65535个字符
- mediumtext 可变长度,最多2的24次方-1个字符
- longtext可变长度,最多2的32次方-1个字符
- BINARY(M) 固定长度,可存二进制或字符,允许长度为0-M字节,
- VARBINARY(M) 可变长度,可存二进制或字符,允许长度为0-M字节
- 内建类型:ENUM枚举, SET集合
-
二进制数据:BLOB
- BLOB和text存储方式不同,TEXT以文本方式存储,英文存储区分大小写,而Blob是以二进制方式存储,不分大小写
- BLOB存储的数据只能整体读出
- TEXT可以指定字符集,BLOB不用指定字符集
-
日期时间类型
- date:日期'2008-12-2'
- time:时间'12:25:36'
- datetime:日期时间'2008-12-2 22:06:44'
- timestamp:自动存储记录修改时间
字段里的时间数据会随其他字段修改的时候自动刷新,这个数据类型的字段可以存放这条记录最后被修改的时间 - YEAR(2), YEAR(4):年份
实验1:创建数据库hellodb并按下表设置建立第一个表student
列名 | id | name | age | gender |
---|---|---|---|---|
含义 | 学号 | 姓名 | 年龄 | 性别 |
类型 | 数值 | 字符串 | 数值 | 字符串 |
范围 | 0-200 | 不超过20个字符 | 0-100 | 1个字符 |
其他 | 主键 | 不允许为空 | 无 | 默认为"m" |
create database hellodb;
use hellodb;
create table student (id tinyint unsigned primary key, name varchar(20) not null, age tinyint unsigned, gender char(1) default "m");
desc student;
- 实验2:在hellodb数据库中创建表student1,字段设置与实验1基本相同,唯一的区别是:id和name构成复合主键
use hellodb;
create table student1 (id tinyint unsigned, name varchar(20) not null, age tinyint unsigned, gender char(1) default "m", primary key(id, name));
desc student1;
(3)修改表操作
- 语法:
ALTER TABLE 'tbl_name'
ADD col_name data_type [FIRST|AFTER col_name] //添加字段
CHANGE COLUMN old_col_name new_col_name data_type //修改字段名
MODIFY col_name data_type //修改字段属性
DROP COLUMN col_name //删除字段
-
实验3:对数据库hellodb的表student一次做如下操作:
- 在name字段后增加字段phone,类型为varchar(11)
alter table student add phone varchar(11) after name;
- 修改phone字段的属性为int
alter table student modify phone int;
- 将name字段定义为唯一键
alter table student add unique key(name);
- 建立age字段的索引
alter table student add index(age);
show indexes from student;
查看表student建立索引的字段
主键和唯一键都会自动建立索引,name字段的索引也可以看到
- 删除phone字段
alter table student drop phone;
- 在name字段后增加字段phone,类型为varchar(11)
(4)索引
-
索引是特殊数据结构,定义查找时作为查找条件的字段
- 优点:提高查询速度
- 缺点:占用额外空间,影响插入速度
创建索引:必须要有索引名称
CREATE INDEX index_name ON tbl_name(index_col_name,...);
删除索引:
DROP INDEX index_name ON tbl_name;
查看索引:
SHOW INDEXES FROM [db_name.]tbl_name;
-
实验4:索引的添加、查看、删除
- 添加表studen字段gender的索引
create index genderindex on student(gender);
- 查看表student的索引(竖列显示)
show indexes from student\G;
- 删除表student字段gender的索引
drop index genderindex on student;
- 添加表studen字段gender的索引
(5)DML语句:INSERT, UPDATE, DELETE
INSERT:插入行
INSERT [INTO] tbl_name [(col_name,...)] {VALUES | VALUE} (val1,...),(...),...
UPDATE:更新行
UPDATE tbl_name SET col1=val1, col2=val2, ... [WHERE clause];
DELETE:删除行
DELETE FROM tbl_name [WHERE clause];
TRUNCATE TABLE tbl_name
:清空表-
实验5:SQL的DML语句应用
- 测试1:按照下表的内容,对表student进行赋值
id name age gender 1 zhao 25 m 2 qian 18 f 3 sun 30 m 4 li 27 m 5 zhou 22 f insert into student (id, name, age, gender) values (1, 'zhao', 25, 'm'); //完整写法 insert into student (name, id, gender, age) values ('qian', 2, 'f', 18); //注意顺序 insert into student values (3, 'sun', 30, 'm'); //可以省略字段描述,但赋值按照字段默认顺序 insert into student values (4, 'li', 27, 'm'), (5, 'zhou', 22, 'f'); //可以一次赋多个值
-
测试2:复制student表并命名为表student2,清空表中的内容
create table student2 select * from student
当空表的字段设置与原表完全相同时,可以使用insert语句复制表内容:
insert into student2 select * from student;
truncate table student2
truncate语句的效率比delete高,但是由于truncate不记录日志,删除后的信息无法恢复 测试3:修改、删除表记录
将zhao的年龄改为24
update student set age=24 where id=1
将li的年龄改为29,性别改为f
update student set age=29, gender='f' where name='li'
删除name为li的记录
delete from student where name='li';
(6)DQL语句:SELECT
语法:
SELECT col1,col2,... FROM tbl_name [WHERE clause] [ORDER BY 'col_name' [DESC]] [LIMIT [m,]n];
Limit m,n:跳过m个,要n个字段表示法:
*:所有字段
AS:字段别名,col1 AS alias1-
WHERE 子句:条件描述方式
- 操作符:
- 关系:
>, <, >=, <=, ==, !=
- 范围:
BETWEEN ... AND ...
- 模糊匹配 LIKE
%:任意长度的任意字符
_:任意单个字符 - 正则表达式模式匹配:
RLIKE
- 空,非空判断:
IS NULL ,IS NOT NULL
- 枚举:
IN (val1,val2,…)
- 关系:
- 条件逻辑操作:
and,or,not
- 操作符:
-
实验6:SELECT语句的使用
当前表student内容如下:id name age gender 1 zhao 25 m 2 qian 18 f 3 sun 30 m 4 li 27 m 5 zhou 22 f 6 wu 17 m 7 zheng 29 NULL 8 wang 33 NULL 查询本表信息,依次实现以下功能:
- 查询本表中字段id, name,age的信息,显示时id字段显示“编号”,name字段显示“姓名”,age字段显示“年龄”
select id as 编号, name as 姓名, age as 年龄 from student;
- 查询本表中年龄大于等于20并且小于等于30的记录
select * from student where age >= 20 and age <= 30;
或者
select * from student where age between 20 and 30;
- 查询本表中姓名以'z'开头的记录,输出时以年龄升序排序
select * from student where name like 'z%' order by age;
- 查询本表中姓名不以'w'开头,并且不以'n'结尾的记录
select * from student where name rlike '^[^w].*[^n]$';
- 查询本表中性别信息为空的记录,输出时以编号降序排序
select * from student where gender is null order by id desc;
- 查询本表中姓名为"qian", "li", "zhou"的记录
select * from student where name in ('qian', 'li', 'zhou');
- 查询本表中字段id, name,age的信息,显示时id字段显示“编号”,name字段显示“姓名”,age字段显示“年龄”
(7)用户账号管理
格式:
'user'@'host'
user:用户名
host:允许用户通过哪些主机远程连接mysqld服务,包含:
IP、网络地址、主机名、通配符(%和_)创建用户:
CREATE USER 'username'@'host' [IDENTIFIED BY 'password'];
查看当前用户:
SELECT user();
查看用户:
SELECT user,host,password FROM user;
删除用户:
DROP USER 'username'@'host';
-
更改口令:
- 方法一:
SET PASSWORD FOR 'user'@'host' = PASSWORD('password');
- 方法二:
mysqladmin -u root -pold_password password 'new_password'’
- 方法一:
(8)授权
-
给用户授权:
GRANT priv_type,... ON [object_type] db_name.tb_name TO 'user'@'host' [IDENTIFIED BY 'password'];
- priv_type:ALL [INSERT, UPDATE, DELETE, SELECT...]
- db_name.tb_name:
*.*
:所有库的所有表
db_name.*
:指定库的所有表
db_name.tb_name
:指定库的指定表
db_name.routine_name
:指定库的存储过程和函数
查看指定用户获得的授权:
SHOW GRANTS FOR 'user'@'host';
回收授权:
REVOKE priv_type, ... ON db_name.tb_name FROM 'user'@'host
FLUSH PRIVILEGES
:手动让MariaDB的服务进程重读授权表-
实验7:用户账号管理、授权管理
创建账号
hellopeiyang@192.168.136.130
并授权其可以查询和添加hellodb数据库中的所有表,密码为'hello'
grant select, insert on hellodb.* to hellopeiyang@192.168.136.130 identified by 'hello';
查看账号
hellopeiyang@192.168.136.130
获得的授权
show grants for hellopeiyang@192.168.136.130
;回收账号
hellopeiyang@192.168.136.130
在hellodb数据库的所有表的全部授权
revoke all on hellodb.* from hellopeiyang@192.168.136.130;
删除账号
hellopeiyang@192.168.136.130
drop user hellopeiyang@192.168.136.130;