1. 什么是数据库
数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,
每个数据库都有一个或多个不同的API用于创建,访问,管理,搜索和复制所保存的数据。
我们也可以将数据存储在文件中,但是在文件中读写数据速度相对较慢。
所以,现在我们使用RDBMS来存储和管理的大数据量。所谓的关系型数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。
RDBMS即关系数据库管理系统(Relational Database Management System)的特点:
- 数据以表格的形式出现
- 每行为各种记录名称
- 每列为记录名称所对应的数据域
- 许多的行和列组成一张表单
- 若干的表单组成database
2. RDBMS 术语
在我们开始学习MySQL 数据库前,让我们先了解下RDBMS的一些术语:
- 数据库(database): 数据库是一些关联表的集合。
- 数据表: 表是数据的矩阵。在一个数据库中的表看起来像一个简单的电子表格。
- 列(column): 一列(数据元素) 包含了相同的数据, 例如邮政编码的数据。
- 行:一行(=元组,或记录)是一组相关的数据,例如一条用户订阅的数据。
- 冗余:存储两倍数据,冗余降低了性能,但提高了数据的安全性。
- 主键(Primary key):主键是唯一的。一个数据表中只能包含一个主键。你可以使用主键来查询数据。
- 外键:外键用于关联两个表。
- 复合键:复合键(组合键)将多个列作为一个索引键,一般用于复合索引。
- 索引:使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构。类似于书籍的目录。
- 参照完整性: 参照的完整性要求关系中不允许引用不存在的实体。与实体完整性是关系模型必须满足的完整性约束条件,目的是保证数据的一致性。
3. 安装配置
官网下载页面:https://dev.mysql.com/downloads/,一般选择社区版
新版本8.0在安装过程中需要设置登录密码
安装之后需要配置路径,打开终端:
- 执行vim ~/.bash_profile
- 在该文件下添加PATH=$PATH:/usr/local/mysql/bin,然后按下:wq退出vim的编辑
- 终端输入souce ~/.bash.profile更新设置生效(否则只能重启终端)
- 终端运行mysql -u root –p,输入登录密码,成功进入MySQL编辑
4. 常用命令
登陆:mysql –u root –p
需要输入密码:Enter password:******
创建数据库:CREATE DATABASE test;
删除数据库:DROP DATABASE test;
查看数据库:SHOW DATABASES;
选择数据库:use test;
列出该库中的所有表:SHOW TABLES;
列出表的列信息:SHOW COLUMNS FROM TRAN;
创建数据表:CREATE
创建MySQL数据表需要以下信息:表名、表字段名、定义每个表字段
例如:
CREATE TABLE test_1
(
Id INT AUTO_INCREMENT,
Title VARCHAR(100) NOT NULL,
Author VARCHAR(40) NOT NULL,
Date DATE,
PRIMARY KEY (Id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
PRIMARY KEY (Id)——每一个表都必须定义一个主键
AUTO_INCREMENT定义列为自增的属性,一般用于主键,数值会自动加1
ENGINE 设置存储引擎,CHARSET 设置编码。
Id、Title等表名不需要用单引号或双引号来引用
如果你不想字段为 NULL 可以设置字段的属性为 NOT NULL, 在操作数据库时如果输入该字段的数据为NULL ,就会报错。
- 删除数据表:DROP TABLE table_1;
- 插入数据:INSERT INTO
INSERT INTO test_1
(title, author, date)
VALUES ("MySQL", "教程", NOW());
NOW()函数以2018-08-14格式展示当前日期
若添加完整一行数据,(title,author,date)的列名可以省略
箭头标记 -> 不是 SQL 语句的一部分,它仅仅表示一个新行,如果一条SQL语句太长,我们可以通过回车键来创建一个新行来编写 SQL 语句,SQL 语句的命令结束符为分号 ;。
查询数据:SELECT … FROM …
例1:
SELECT Title,Author FROM test_2
WHERE Title = 'MySQL';
WHERE 子句类似于程序语言中的 if 条件,根据 MySQL 表中的字段值来读取指定的数据。展示结果如下,由此也可看出sql语言不区分大小写
例2:
SELECT * FROM test_1,test_2;
SELECT 可以选择多个表,如下图两个表会分排且展示时会将数目较少的列表拉长
例3:可以使用 LIMIT 来设定返回的记录数
SELECT * FROM test_2 LIMIT 2;
例4:
SELECT * FROM test_2 LIMIT 2,1;
SELECT * FROM test_2 LIMIT 1 OFFSET 2
// 语句1和2均返回表test_2的第3行
// 语句2中的1表示返回1行,3表示从表的第3行开始
OFFSET表示偏移量,注意OFFSET 2表示从第三行开始记录
修改或更新数据:UPDATE
例1:
UPDATE test_2 SET DATE='2017-06-01' WHERE ID=3;
例2:不限定where的条件的话将会修改整个列
UPDATE test_2 SET DATE='2017-06-01';
删除数据:DELETE
DELETE FROM test_1 WHERE ID=1;
该语句作用是删除test_1第一行,若不指定where将删除整个表的数据
设定获取数据的条件:LIKE
例1:
UPDATE TEST_2 SET DATE=NOW() WHERE Title LIKE 'L%';
可以使用LIKE子句代替等号 =。
LIKE 通常与 % 一同使用,类似于一个元字符的搜索。
可以在 DELETE 或 UPDATE 命令中使用 WHERE...LIKE 子句来指定条件。
例2:
select * from test_2 where title not like 'm_s%';
例3:选择以Title中m、S开头的的数据
SELECT * FROM test_2 WHERE Title RLIKE '^[mS]';
SQL通配符:只能与LIKE一起使用
通配符 | 描述 |
---|---|
% | 替代一个或多个字符 |
_ | 仅替代一个字符 |
[charlist] | 字符列中的任何单一字符 |
[^charlist] / [!charlist] | 非字符列中的任何单一字符 |
但注意:MySQL的like子句不能识别[charlist],需要使用rlike,所以尽量不使用后面两种通配符。
¬
连接两个以上的select结果组合到一个结果组合中:UNION
语法格式
SELECT expression1, expression2, ... expression_n
FROM tables
[WHERE conditions]
UNION [ALL | DISTINCT]
DISTINCT: 可选,删除结果集中重复的数据。默认情况下 UNION 操作符已经删除了重复数据,所以 DISTINCT 修饰符对结果没有影响。
ALL:可选,返回所有结果,包含重复数据
例1:union
例2:union all
例3:带where
排序:ORDER BY
SELECT * FROM TEST_2 ORDER BY DATE (ASC); ——默认升序
SELECT * FROM TEST_2 ORDER BY DATE DESC; ——降序
分组做统计:GROUP BY
例1:将数据表按名字进行分组,再统计每个人登录的次数:
SELECT NAME,COUNT(*) FROM EMPLOYEE GROUP BY NAME;
count()函数是用来统计表中记录的一个函数,返回匹配条件的行数。
count(*)---包括所有列,返回表中的记录数,相当于统计表的行数,在统计结果的时候,不会忽略列值为NULL的记录。
count(列名)---只包括列名指定列,返回指定列的记录数,在统计结果的时候,会忽略列值为NULL的记录(不包括空字符串和0)。
例2: with rollup做统计
SELECT NAME, SUM(singin) as singin_count FROM employee GROUP BY name WITH ROLLUP;
- SUM( )函数统计()内该列的数目
- 其中NULL表示所有人的登陆次数
- WITH ROLLUP 可以实现在分组统计数据基础上再进行相同的统计(SUM,AVG,COUNT…)。
例3:
SELECT COALESCE(name,'总数'),SUM(singin) as singin_count FROyee GROUP BY name WITH ROLLUP;
COALESECE()函数:返回参数(列名)中第一个非NULL的字段值,即若a不为NULL ,coalesce(a,b,c)返回a,若参数全为NULL则返回NULL。
多个表连接的使用:JOIN
1. INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录。
SELECT a.title,b.author,b.date FROM test_1 a INNER JOIN test_2 b ON a.title = b.title;
- from后面test_1 a 将test_1替换为a,所以前面可以使用a.title
- FROM test_1 a INNER JOIN test_2 b获取了a、b两个表的匹配关系
- 上面的sql语句实际等于
SELECT a.title,b.author,b.date FROM test_1 a,test_2 b WHERE a.title = b.title;
2. LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录。
SELECT a.title,b.author,b.date FROM test_1 a LEFT JOIN test_2 b ON a.title = b.title;
3. RIGHT JOIN(右连接): 与 LEFT JOIN 相反,用于获取右表所有记录,即使左表没有对应匹配的记录。
SELECT a.title,b.author,b.date FROM test_1 a RIGHT JOIN test_2 b ON a.title = b.title;
NULL值的处理
MySQL中处理NULL使用IS NULL和IS NOT NULL运算符,=和!=对NULL不起作用。而且NULL 值与任何其它值的比较(即使是 NULL)永远返回 false,即 NULL = NULL 返回false 。
• IS NULL: 当列的值是 NULL,此运算符返回 true。
• IS NOT NULL: 当列的值不为 NULL, 运算符返回 true。
• <=>: 比较操作符(不同于=运算符),当比较的的两个值为 NULL 时返回 true。
例1:
SELECT * FROM NUL WHERE COUNT=NULL;
SELECT * FROM NUL WHERE COUNT IS NULL;
SELECT * FROM NUL WHERE COUNT IS NOT NULL;
例2:
SELECT * FROM NUL WHERE COUNT <=> NULL;
修改表字段:ALTER
例1:删除ID表字段来删除列
ALTER TABLE TRAN DROP ID;
当数据表中只剩余一个字段则无法使用DROP来删除字段
例2:添加字段
ALTER TABLE tran ADD id INT;
指定新增字段位置:
设定为第一列:ALTER TABLE tran ADD id INT FIRST;
设定为某个字段之后:ALTER TABLE tran ADD id INT AFTER NAME;
例3:修改字段类型和名称:
ALTER TABLE tran MODIFY NAME VARCHAR(10);
ALTER TABLE tran CHANGE NAME name VARCHAR(10);
例4:对NULL值和默认值的影响:
ALTER TABLE tran MODIFY NAME VARCHAR(10) NOT NULL DEFAULT JAY;
CHANGE不能如此设置
例5:修改或删除字段默认值:
ALTER TABLE tran ALTER NAME SET DEFAULT Jolin;
ALTER TABLE tran ALTER NAME DROP DEFAULT;
例6:修改表名:
ALTER TABLE TRAN RENAME TO TR;
正则表达式(regular expression,REGEXP)
正则表达式就是用来匹配文本的特殊字符串。正则表达式与LIKE子式的区别可以看做是精准查询与模糊查询的区别
语法:WHERE ‘name’ REGEXP ‘exp’
- (^)定位元字符
匹配字符串的开始位置,如“^a”表示以字母a开头的字符串。
- ($)定位元字符
匹配字符串的结束位置,如“X$”表示以字母X结尾的字符串。
- (.)字符
这个字符就是英文下的点,它匹配任何一个字符,包括回车、换行等。
- ({n})元字符
n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
- ({m,n})元字符
m和n为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。
- (*)元字符
星号匹配前面的子表达式0次或多次字符,例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
- (+)元字符
加号加号跟星号的用法类似,匹配前面的子表达式1次或多次字符。+ 等价于 {1,}。
- (?)元字符
问号匹配0次或1次,a?等价于a{0,1}。
- ( | )字符
或查询也叫OR查询,例如,’100|200’匹配包含100或者200的记录
- ([abc])字符
字符集合,匹配包含的任意一个字符,例如, '[abc]' 可以匹配 "plain" 中的 'a'。
- ([^abc])字符
负值字符集合,匹配未包含的任意字符,例如, '[^abc]' 可以匹配 "plain" 中的 'p'。
- ([0-9])字符
匹配一个范围,’[0-9]’等价于’[0123456789]’
- 特殊字符需转义
\[ 匹配左方括号
\\ 匹配反斜杠自己本身
\f 换页
\n 换行
\r 回车
\t 制表符
\v 纵向制表符
在一般的编程语言中,转义一般使用一个反斜线,在Mysql中为什么是两个才行?原因是:Mysql自己需要一个来识别,然后Mysql会将扣除了一个反斜杠的剩余的部分完全的交给正则表达式库解释,所以加起来就是两个了。
- 预定义字符集
类 | 说明 |
---|---|
[:alnum: | 任意数字和字母。相当于[a-zA-Z0-9] |
[:alpha:] | 任意字符。相当于[a-zA-z] |
[:blank:] | 空格和制表。相当于[\t] |
[:cntrl:] | ASCII控制字符(ASCII 0 到31和127) |
[:digit:] | 任意数字。相当于[0-9] |
[:graph:] | 与[:print:]相同,但是不包含空格 |
[:lower:] | 任意的小写字母。相当于[a-z] |
[:print:] | 任意可打印字符 |
[:punct:] | 既不在[:alnum:]又不在[:cntrl:]中的任意字符 |
[:space:] | 包括空格在内的任意空白字符 |
[:upper:] | 任意大写字母。相当于[A-Z] |
[:xdigit:] | 任意十六进制的数字。相当于[a-fA-F0-9] |
事务(Transaction)
1. 什么是事务?
事务:一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元)
MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你既需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!
在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务
事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行
事务用来管理 insert, update, delete 语句(也可以select)
2. 一般来说,事务必须满足ACID 4个条件
• 原子性(Atomicity,或称不可分割性):一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
• 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
• 隔离性(Isolation,又称独立性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。
read uncommitted
- 事物A和事物B,事物A未提交的数据,事物B可以读取到
- 这里读取到的数据叫做“脏数据”
- 这种隔离级别最低,这种级别一般是在理论上存在,数据库隔离级别一般都高于该级别
read committed
- 事物A和事物B,事物A提交的数据,事物B才能读取到
- 这种隔离级别高于读未提交
- 换句话说,对方事物提交之后的数据,我当前事物才能读取到
- 这种级别可以避免“脏数据”
- 这种隔离级别会导致“不可重复读取”
- Oracle默认隔离级别
repeatable read
- 事务A和事务B,事务A提交之后的数据,事务B读取不到
- 事务B是可重复读取数据
- 这种隔离级别高于读已提交
- 换句话说,对方提交之后的数据,我还是读取不到
- 这种隔离级别可以避免“不可重复读取”,达到可重复读取
- 比如1点和2点读到数据是同一个
- MySQL默认级别
- 虽然可以达到可重复读取,但是会导致“幻像读”
serializable
- 事务A和事务B,事务A在操作数据库时,事务B只能排队等待
- 这种隔离级别很少使用,吞吐量太低,用户体验差
- 这种级别可以避免“幻像读”,每一次读取的都是数据库中真实存在数据,事务A与事务B串行。
• 持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。
3. 事物与数据库底层数据
在事物进行过程中,未结束之前,DML语句是不会更改底层数据,只是将历史操作记录一下,在内存中完成记录。只有在事物结束的时候,而且是成功的结束的时候,才会修改底层硬盘文件中的数据
4. 事务控制语句:
==BEGIN或START TRANSACTION==;显式地开启一个事务;
==COMMIT Transaction==;也可以使用COMMIT WORK,不过二者是等价的。COMMIT会提交事务,并使已对数据库进行的所有修改成为永久性的;
==ROLLBACK Transaction==;有可以使用ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
SAVEPOINT identifier;SAVEPOINT允许在事务中创建一个保存点,一个事务中可以有多个SAVEPOINT;
RELEASE SAVEPOINT identifier;删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
ROLLBACK TO identifier;把事务回滚到标记点;
SET TRANSACTION;用来设置事务的隔离级别。InnoDB存储引擎提供事务的隔离级别有读未提交(READ UNCOMMITTED)、读已提交(READ COMMITTED)、可重复读(REPEATABLE READ)和可串行化(SERIALIZABLE)。
5. MYSQL 事务处理主要有两种方法:
- 用 BEGIN, ROLLBACK, COMMIT来实现
BEGIN 开始一个事务
ROLLBACK 事务回滚
COMMIT 事务确认
- 直接用 SET 来改变 MySQL 的自动提交模式:
SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT=1 开启自动提交
6. 举例:
索引:提高MySQL的检索速度。
索引分单列索引和组合索引。
- 单列索引,即一个索引只包含单个列,一个表可以有多个单列索引。也叫主键索引、唯索引、普通索引;
- 组合索引,即一个索引包含多个列。
创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。
实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。
过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。建立索引会占用磁盘空间的索引文件。
实践问题
1. 配置路径
安装后命令行输入mysql –u root –p 提示找不到该命令,发现是没有配置路径;按“安装配置”步骤配置后成功登陆。
若配置完路径登陆时还报错:
Access denied for user 'root'@'localhost' (using password: YES)
请重启终端。
2. 符号格式
实践时在Word边做笔记边在写sql语句,然后copy过命令行运行,一直提示“ERROR 1054:Unknown column ‘”learning sql"' in 'field list' ",几次修改未果,后来觉得可能是Word会自动修改某些引用符号的格式,于是直接在命令行敲入,结果无误。所以为了保证半角符号的准确性,尽量在命令行页面敲入语句。
3. 查询多个表出错
了解到查询语句可以使用多个表,于是写了一个语句:
select author from test_1,test_2 where author = 'paul';
但报错:
ERROR 1052 (23000): Column 'author' in field list is ambiguous
即语句中的author有歧义,mysql不知道它应该是哪一个表里的列名,修改成:
select test_1.author,test_2.author from test_1,test_2 where ((test_1.author = 'paul') and (test_2.author = 'jiaocheng'));
问题解决。