安装和配置
安装
1.下载免安装版,将其解压之后,将bin加入path,新建文件夹data, 新建my.ini文件,输入:
1 | [mysqld] |
2.管理员身份打开cmd, 输入:
1 | mysqld --initialize --user=mysql --console |
记录随机密码,之后分别输入以下来启动MySQL:
1 | mysqld --install MySQL |
3.登录MySQL。
1 | mysql -uroot -p |
以上可选加入参数:-h:ip或者localhost
输入刚才记录的随机密码即可登录。登录之后可设置自定义密码:
1 | set password for root@localhost=Password("0119") |
4.安装MySQL的Workbench。
配置
在MySQL里面设置只是临时修改,MySQL重启之后会恢复为默认设置,因此为了永久修改需要修改配置文件。
设置数据表和数据库与Server的编码方式。可以在终端登陆mysql,之后输入\s查看编码方式。修改方式为,将my.ini文件替换为以下内容:
1 | [mysql] |
ps: 以上
...\mysql-5.7.11-winx64为MySQL免安装版的解压路径。
Python 连接和使用
通过Python 3与MySQL连接可通过pymysql实现。
1 | pip install pymysql |
1.连接数据库
1 | import pymysql |
2.执行SQL语句
1 | sql = 'DROP TABLE IF EXISTS tbl_name' |
3.fetch操作
- fetchone(): 该方法获取下一个查询结果集。结果集是一个对象
- fetchall(): 接收全部的返回结果行.
- rowcount: 这是一个只读属性,并返回执行execute()方法后影响的行数。
1 | try: |
基本语法
- 以”;”结尾。
- 关键词不区分大小写,但是推荐用大写。
- 单行注释采用 “# 注释”、”— 注释”,多行注释采用”/*注释*/“。
数据类型
1. 数值类型
1.整数型
tinyint:占用1字节- 有符号:-128到127($-2^7$到$2^7-1$)
- 无符号:0到255(0到$2^8-1$)
smallint:占用2字节- 有符号:-32768到32767($-2^{15}$到$2^{15}-1$)
- 无符号:0到65535(0到$2^{16}-1$)
mediumint:占用3字节- 有符号:到$2^{23}-1$
- 无符号:0到$2^{24}-1$
int:占用4字节- 有符号:$-2^{31}$到$2^{31}-1$
- 无符号:0到$2^{32}-1$
bigint:占用8字节- 有符号:$-2^{63}$到$2^{63}-1$
- 无符号:0到$2^{64}-1$
2.小数型
(1)浮点型
float:float(m, d)。单精度浮点型8位精度(4字节),m总位数,d小数位。double:double(m, d)。双精度浮点型16位精度(8字节),m总位数,d小数位。(2)定点型
decimal:decimal(m, d)。精确数字,m总位数,d小数位。例如 decimal(4,2)最大值位99.99。
2. 字符串类型
char:char(n)。0~255字节,定长,不够用空格填充,多余截取,字符串所占用的字节数总是为n。char存取速度比varchar快,但会造成空间浪费。varchar:varchar(n)。0-65535字节,可变长度,根据字符串长度调整长度,字符串所占用的字节数小于等于n。tinytext:0-255字节。短文本字符串。text:0-65535字节,长文本。mediumtext:0-$2^{24}-1$字节,中等长度文本。longtext:0-$2^{32}-1$字节,极大文本。enum:占用1或2个字节,取决于枚举值的位数(最多65535个值)。set:1、2、3、4或8个字节,取决于set成员的数目(最多64个成员)。
3. 日期类型
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:SStimestamp:占用8字节,范围为1970-01-01 00:00:00 至 2037年某时,格式为YYYYmmdd HHMMSS。
建议用int存储时间的时间戳。
修饰关键字
unsigned:无符号。auto_increment:自增。default:默认值。comment:注释,字段解释说明。not null:非空。unique:唯一索引。index:普通索引。primary key:主键。
auto_increment必须指定为primary key。
运算符
- 算术运算符:
+,-,*,/,DIV,%和MOD。10 DIV 4等于2.
- 比较运算符:
=:赋值和判断是否相等。!=,<>:不等于。>,<,>=,<=:大小比较。BETWEEN...AND表示位于…之间。NOT BETWEEN...AND不在…之间。IN表示在集合里面。NOT IN表示不再集合里面。<=>严格比较两个NULL值是否相等。两者均为NULL时取值为1,一者为NULL时取值为0.LIKE模糊匹配。REGEXP或RLIKE正则表达式匹配。IS NULL为空。IS NOT NULL不为空。
- 逻辑运算符
NOT或!表示逻辑非。OR或者||表示 逻辑或。AND或者&&表示 逻辑与。XOR表示逻辑异或。
- 位运算符
&表示按位与。|表示按位或。^表示按位异或。!表示取反。<<表示左移。>>表示右移。
函数
MySQL提供了很多用于字符串、数值、日期的转换函数,以及一些高级函数。以下介绍一些常见的高级函数,更多详细内容可以参考 MySQL 函数。
IF(expr, v1, v2)- 功能:如果表达式expr成立,返回结果v1;否则,返回结果v2。
- 示例:
SELECT IF(1>0, '正确', '错误');
IFNULL(v1, v2)- 功能:如果v1的值不为NULL,则返回v1,否则返回v2。
- 示例:
SELECT IFNULL(null, 'Hello');
ISNULL(expr)- 功能:判断表达式是否为NULL。
- 示例:
SELECT ISNULL(NULL);
NULLIF(expr1, expr2)- 功能:比较两个字符串,如果字符串 expr1 与 expr2 相等 返回 NULL,否则返回 expr1。
- 示例:
SELECT NULLIF(25, 25);
CAST(x AS type)- 功能:转换数据类型
- 示例:
SELECT CAST("2017-08-29" AS DATE);
SQL语句分类
DDL:Data Definition Language。用于创建、删除、修改 库表结构。DML:Data Manipulation Language。用于增、删、改 表的记录。DCL:Data Control Language。用于用户的创建以及授权。DQL:Data Query Language。用于查询数据。
数据定义 DDL
数据库相关操作
1.查看所有数据库
1 | SHOW DATABASES; |
2.切换 / 使用 数据库
1 | USE db_name; |
3.创建数据库
1 | # 最简单的创建数据库 |
ps:以上,{}表示多选一,[]表示可选可不选。
4.修改数据库
1 | ALTER {DATABASE | SCHEMA} [db_name] [DEFAULT] CHARACTER SET [=] charset_name; |
5.删除数据库
1 | DROP {DATABASE | SCHEMA} [IF EXISTS] db_name; |
数据表相关操作
数据表设计的三范式:
- 第一范式——原子性:数据表的每一列均不可分解;
- 第二范式:除了主键之外的其他列,均与主键有关。即,一个表只描述一件事情。例如订单表只描述订单信息,产品表只描述产品信息。
- 第三范式:数据表中的列至于主键直接相关,不是间接相关,每一列只依赖于主键。例如,订单表只需要有用户的id即可,不需要关联用户的其他信息,因为用户的其他信息可以通过用户id在用户表中查询到。避免设计冗余。
1.查看所有数据表
1 | SHOW TABLES [FROM db_name] [LIKE 'pattern' | WHERE expr] |
2.查看数据表信息
1 | # 查看数据表中的所有列 |
3.创建数据表
1 | # 创建数据表 |
1 | # 以下为创建数据表时添加一些约束的示例 |
4.修改数据表
1 | # 修改表名 |
1 | # 以下为修改数据表时添加/删除一些约束的示例 |
ALTER可以用于修改数据库、数据表名、数据字段。
5.删除数据表
1 | DROP TABLE tbl_name ; |
数据操作 DML
插入数据记录
1 | # 插入一条数据,建议插入哪些列就指定哪些列名 |
命令行插入汉字显示乱码的问题:
- 在插入之前设置编码方式(临时性质的):
set names gbk;- 修改配置文件。
更新数据记录
1 | UPDATE 表名 SET 列名1={value | expr | DEFAULT} [, 列名2 = {expr | DEFAULT}] … [WHERE 更新条件] |
删除数据记录
1 | DELETE FROM 表名 WHERE 删除条件; |
delete,drop,truncate 都有删除表的作用,区别在于:
- 1、delete 和 truncate 仅仅删除表数据,drop 连表数据和表结构一起删除,打个比方,delete 是单杀,truncate 是团灭,drop 是把电脑摔了。
- 2、delete 是 DML 语句,操作完以后如果没有不想提交事务还可以回滚,truncate 和 drop 是 DDL 语句,操作完马上生效,不能回滚,打个比方,delete 是发微信说分手,后悔还可以撤回,truncate 和 drop 是直接扇耳光说滚,不能反悔。
- 3、执行的速度上,drop>truncate>delete,打个比方,drop 是神舟火箭,truncate 是和谐号动车,delete 是自行车。
数据控制 DCL
ps:涉及用户、权限的更新一般需要
FLUSH PRIVILEGES;刷新权限才能生效。
指定IP访问
实际上是通过修改mysql数据库下user表中user=root项的host(user=root的host默认值包括了127.0.0.1、::1和localhost)。
1 | USE mysql; |
之后只有在登陆时输入mysql -uroot -h192.168.0.5 -p才能登录,否则默认采用localhost的host登录。
修改密码
以下介绍三种修改密码的方法。
1.修改mysql数据库下user数据表中user=root的password。
1 | USE mysql; |
2.使用MySQL安装路径下bin->mysqladmin。
1 | # 在终端中直接运行以下命令,将原密码0119修改为新密码admin |
3.在mysql界面中直接设置密码
1 | SET password for root@localhost=Password("0119") |
忘记密码
- 第一步,停止
mysql.exe服务。 - 在命令行中运行 :
1 | mysqld --skip-grant-tables |
用户创建
1 | # 创建用户 |
用户授权
1 | # 查看用户权限 |
用户删除
1 | # 删除用户 |
数据查询 DQL
条件查询
1 | # 条件查询通用表达式 |
数据排序
1 | SELECT * FROM 表名 ORDER BY 字段名 [ASC|DESC] |
聚合函数
1 | # 聚合函数 |
NULL值处理:
1
2 > ifnull(列名, 新值) #如果该列值为NULL,则替换为新值
>
数据分组
1 | # 按字段分组,按字段顺序排序,过滤符合表达式的项 |
1 | # 按字段分组,将同组的其他字段拼接起来 |
连接查询
1 | SELECT 新表名1.列名1,新表名2.列名2 FROM 表名1 AS 新表名1,表名2 AS 新表名2 WHERE 查询条件; |
联合查询
1 | SELECT 查询1 UNION [ALL | DINSTINCT] 查询2; |
子查询
1 | SELECT 查询1 WHERE 列名 in 查询2; |
Limit
1 | SELECT 查询1[ LIMIT N][ OFFSET M]; |
字符集和存储引擎
存储引擎
- MyISAM
- 全文索引,不支持事务。
- 表级锁,崩溃恢复支持不好。
- InnoDB
- 支持事务,不支持全文索引(5.6版本后开始支持,5.6开始默认数据库引擎是InnoDB)
- 速度快,推荐。
- 行级锁,崩溃恢复支持较好。
1.查看数据库引擎
1 | # 1.通过数据表查看引擎 |
2.修改数据库引擎
1 | CREATE TABLE test(name varchar(5)) ENGINE=InnoDB; |
字符编码
1.查看字符编码
1 | # 查看所有字符编码 |
2.修改字符编码
1 | # 1. 创建/修改数据库时声明字符编码 |
3.修改默认字符编码
修改my.ini文件:
1 | [mysql] |
4.字符校对
utf8_general_ci支持不区分大小写。
1 | CREATE TABLE tbl_name(name varchar(5)) ENGINE=InnoDB charset=utf8 collate=utf8_general_ci; |
SQL优化
慢查询
1.开启记录慢查询日志
1 | # 查找记录慢查询字段 |
此时可在slow_query_log_file对应的文件名里记录慢查询的查询记录。
2.分析慢查询
1 | # 解释查询语句的执行结果,包括搜索了多少行之类的信息 |
3.慢查询优化
给查询条件中的字段添加索引。
1 | ALTER TABLE tbl_name ADD INDEX(pid); |
数据库缓存
1 | SHOW STATUS LIKE '%qcache%'; |
在一次查询之后将结果存入缓存,后续查找可以直接去缓存取结果,极大提高效率。
1 | # 关闭缓存 |
其他优化
- 尽量减少使用
SELECT *; - 减少使用
LIKE的左模糊查询,可以使用右模糊; - 使用
LIMIT; - 查询条件中尽量减少表达式运算。
其他
重复数据处理
数据表中可能存在重复的记录,有些情况我们允许重复数据的存在,但有时候我们也需要删除这些重复的数据。
1.防止表中出现重复数据
一般来说,如果为数据表的某个字段为主键或者唯一约束,则可确保不出现重复数据。如果我们设置了唯一索引,那么在插入重复数据时,SQL 语句将无法执行成功,并抛出错。
INSERT IGNORE INTO 当插入数据时,在设置了记录的唯一性后,如果插入重复数据,将不返回错误,只以警告形式返回。 而 REPLACE INTO 如果存在 primary 或 unique 相同的记录,则先删除掉,再插入新记录。
2.统计重复数据
采用GROUP BY对特定字段进行分组,通过HAVING子句过滤重复次数大于1的即可统计重复数据。
1 | SELECT COUNT(*) as repetitions, last_name, first_name FROM person_tbl GROUP BY last_name, first_name HAVING repetitions > 1; |
3.过滤重复数据
- 在 SELECT 语句中使用 DISTINCT 关键字来过滤重复数据;
1 | SELECT DISTINCT last_name, first_name FROM person_tbl; |
- 使用 GROUP BY 来读取数据表中不重复的数据。
1 | SELECT last_name, first_name FROM person_tbl GROUP BY (last_name, first_name); |
4.删除重复数据
- 新建数据表,按Group分组,之后删除旧表,更新新表。
1 | CREATE TABLE tmp SELECT last_name, first_name, sex FROM person_tbl GROUP BY (last_name, first_name, sex); |
- 为数据表添加主键索引。
1 | ALTER IGNORE TABLE person_tbl ADD PRIMARY KEY (last_name, first_name); |
MySQL导入
1.MySQL命令
1 | mysql -u用户名 -p密码 < 要导入的数据库数据(runoob.sql) |
2.Source命令
1 | CREATE DATABASE abc; # 创建数据库 |
3. LOAD DATA
1 | LOAD DATA LOCAL INFILE 'dump.txt' INTO TABLE mytbl [FIELDS [TERMINATED BY ','] [[OPTIONALLY] ENCLOSED BY '"']] [LINES [TERMINATED BY '\n']]; |
默认情况下是按照数据文件中列的顺序插入数据的,如果数据文件中的列与插入表中的列不一致,则需要指定列的顺序。
1 | LOAD DATA LOCAL INFILE 'dump.txt' INTO TABLE mytbl (b, c, a); |
4. mysqlimport
1 | mysqlimport -u root -p --local --fields-terminated-by=":" --columns=b,c,a --lines-terminated-by="\r\n" database_name dump.txt |
mysqlimport常用可选参数说明:
- -d or —delete:新数据导入数据表中之前删除数据数据表中的所有信息。
- -f or —force:不管是否遇到错误,mysqlimport将强制继续插入数据。
- -i or —ignore:mysqlimport跳过或者忽略那些有相同唯一 关键字的行, 导入文件中的数据将被忽略。
- -l or -lock-tables:数据被插入之前锁住表,这样就防止了, 你在更新数据库时,用户的查询和更新受到影响。
- -r or -replace:这个选项与-i选项的作用相反;此选项将替代 表中有相同唯一关键字的记录。
- —fields-enclosed- by= char:指定文本文件中数据的记录时以什么括起的, 很多情况下 数据以双引号括起。 默认的情况下数据是没有被字符括起的。
- —fields-terminated- by=char:指定各个数据的值之间的分隔符,在句号分隔的文件中, 分隔符是句号。您可以用此选项指定数据之间的分隔符。 默认的分隔符是跳格符(Tab)。
- —lines-terminated- by=str:此选项指定文本文件中行与行之间数据的分隔字符串 或者字符。 默认的情况下mysqlimport以newline为行分隔符。 您可以选择用一个字符串来替代一个单个的字符: 一个新行或者一个回车。
- -v :显示版本(version)
- -p: 提示输入密码(password)等。
MYSQL导出
1.SELECT INTO OUTFILE
1 | SELECT * FROM tbl_name INTO OUTFILE '/tmp/runoob.txt' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\r\n'; |
2.mysqldump
1 | mysqldump -u root -p --no-create-info --tab=/tmp RUNOOB runoob_tbl |
事务
- 只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
- 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行,可以避免例如转账过程中A的钱转出去但是B没收到的情况。
- 事务用来管理 insert,update,delete 语句。
一般来说,事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。
- 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
- 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
- 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。
1 | START TRANSACTION; # 开启事务 |
事务控制语句
- 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。
事务处理主要有两种方法
1、用 BEGIN, ROLLBACK, COMMIT来实现
- BEGIN 开始一个事务
- ROLLBACK 事务回滚
- COMMIT 事务确认
2、直接用 SET 来改变 MySQL 的自动提交模式:
- SET AUTOCOMMIT=0 禁止自动提交
- SET AUTOCOMMIT=1 开启自动提交
视图
等价于将SELECT查询结果另存。
1 | CREATE VIEW test_view(name, email) AS SELECT name, email FROM student WHERE id=2; |
索引
索引可以大大提高MySQL的检索速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE,也会占用磁盘空间的索引文件。索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。创建索引时,需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。
索引主要包括普通索引、唯一索引(值必须唯一,但允许有空值)等。索引可以在创建表时直接指定,也可后续修改,或者后续创建和删除。
1 | # 1. 创建索引 |