# MySQL 笔记 1
# SQL
- DDL
- DML
- DQL
- DCL
# 数据库存储引擎
- InnoDB
- MyISAM
- Memory
- Merge
- Archive
- Federated
- CSV
- BlackHole
# DDL
# 创建数据库
CREATE DATABASE <库名>;
# 删除数据库
DROP DATABASE <库名>;
# 查看数据库
SHOW DATABASES;
# 查看表
SHOW TABLES;
# 创建表
CREATE TABLE <表名>
(
<列名1>, <数据类型> [列级别约束条件] [默认值] [注释],
<列名1>, <数据类型> [列级别约束条件] [默认值] [注释],
... ...
[表级别约束条件]
);
/*
主键约束
单字段主键:字段名 数据类型 PRIMARY KEY [默认值]
多字段联合主键:PRIMARY KEY [字段1, 字段2, ..., 字段n]
*/
/*
外键约束
[CONSTRAINT <外键名>] FOREIGN KEY 列名1 [,列名2, ...]
REFERENCES <主表名> 主键列1 [,主键列2, ...]
*/
/*
非空约束
字段名 数据类型 NOT NULL
*/
/*
唯一性约束
字段名 数据类型 UNIQUE
*/
/*
默认约束
字段名 数据类型 DEFAULT 默认值
*/
/*
自增属性
字段名 数据类型 AUTO_INCREMENT
*/
# 查看表结构
DESCRIBE <表名>;
DESC <表名>;
SHOW CREATE TABLE <表名>;
# 修改表结构
## 修改表名
ALTER TABLE <旧表名> RENAME [TO] <新表名>;
## 修改字段数据类型
ALTER TABLE <表名> MODIFY <字段名> <数据类型>
## 修改字段名(类型)
ALTER TABLE <表名> CHANGE <旧字段名> <新字段名> <新数据类型>;
## 添加字段
ALTER TABLE <表名> ADD <新字段名> <数据类型> [约束条件] [FIRST|AFTER 已存在字段名];
## 删除字段
ALTER TABLE <表名> DROP <字段名>;
## 修改字段的排列位置
ALTER TABLE <表名> MODIFY <字段1> <数据类型> FIRST|AFTER <字段2>;
## 更改表的存储引擎
ALTER TABLE <表名> ENGINE=<新存储引擎名>;
## 删除表外键约束
ALTER TABLE <表名> DROP FOREGIN KEY <外键约束名>;
## 删除表
DROP TABLE [IF EXISTS] 表1, 表2, ..., 表n;
# 数据类型
- 整数类型:TINYINT, SMALLINT, MEDIUMINT, INT(INTEGER), BIGINT
- 浮点数类型:FLOAT, DOUBLE
- 定点数类型:DECIMAL
- 日期与时间类型:DATETIME, DATE, TIMESTAMP, TIME, YEAR
- 字符串类型:CHAR, VARCHAR, BINARY, VARBINARY, BLOB, TEXT, ENUM, SET
- 二进制类型:BIT, BINARY, VARBINARY, TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOG
# 运算符
- 算术运算符
+, -, *, /, %
- 比较运算符
- 运算结果为 1, 0 或 NULL
=, <=>, <>, !=, <=, >=, >, IS NULL, IS NOT NULL, LEAST, GREATEST, BETWEEN ... AND ..., ISNULL, IN, NOT IN, LIKE, REGEXP
- 逻辑运算符
- 运算结果为 TRUE, FALSE, NULL
NOT, !, AND, &&, OR, ||, XOR
- 位操作运算符:
|, &, ^, ~, <<, >> - 运算符的优先级
# 函数
# 数学函数
| 函数 | 作用 |
|---|---|
| ABS(x) | 取绝对值 |
| PI | 返回圆周率 |
| SORT(x) | 取平方根 |
| MOD(x, y) | 取余 |
| CEIL(x), CEILING(x) | 向上取整 |
| FLOOR(x) | 向下取整 |
| RAND(), RAND(x) | 取随机数 |
| ROUND(x), ROUND(x, y), TRUNCATE(x, y) | 四舍五入 |
| SIGN(x) | 符号函数(x 为负、零、正时依次返回 -1、0、1) |
| POW(x, y), POWER(x, y), EXP(y) | 幂函数 |
| LOG(x), LOG10(x) | 对数函数 |
| RADIANS(x), DEGREES(x) | 角度与弧度转换 |
| SIN(x), ASIN(x), COS(x), ACOS(x), TAN(x), ATAN(x) | 三角与反三角函数 |
# 字符串函数
| 函数 | 作用 |
|---|---|
| CHAR_LENGTH(str), LENGTH(str) | 获取字符串字符数/字节长度 |
| CONCAT(s1, s2, ...), CONCAT_WS(x, s1, s2, ...) | 合并字符串 |
| INSERT(s1, x, len, s2) | 替换字符串 |
| LOWER(str), LCASE(str), UPPER(str), UCASE(str) | 转换大小写 |
| LEFT(s, n), RIGHT(s, n) | 获取子字符串 |
| LPAD(s1, len, s2), RPAD(s1, len, s2) | 填充字符串 |
| LTRIM(s), RTRIM(s), TRIM(s) | 删除空格 |
| TRIM(s1 FROM s) | 删除两端指定字符串 s |
| REPEAT(s, n) | 重复生成字符串 |
| SPACE(n) | 生成空格 |
| REPLACE(s, s1, s2) | 替换字符串 |
| STRCMP(s1, s2) | 比较字符串大小(s1 大于、等于、小于 s2 返回 1、0、-1) |
| SUBSTRING(s, n, len), MID(s, n, len) | 获取子串 |
| LOCATE(str1, str), POSITION(str1 IN str), INSTR(str, str1) | 匹配子串 str1 在字符串 str 中开始位置 |
| REVERSE(x) | 字符串逆序 |
| ELT(n, str1, str2, ..., strn) | 返回指定位置的字符串 |
| FILED(s, s1, s2, ...) | 返回指定字符串位置 |
| FIND_IN_SET(s1, s2) | 返回子串 s1 在字符串列表 s2 中的位置 |
| MAKE_SET(x, s1, s2, ...) | 返回 x 的二进制数指定的相应位字符串 |
# 日期和时间函数
| 函数 | 作用 |
|---|---|
| CURDATE(), CURRENT_DATE(), CURRENT_TIMESTAMP(), LOCALTIME(), NOW(), SYSDATE() | 当前日期、时间、日期和时间 |
| UNIX_TIMESTAMP(), UNIX_TIMESTAMP(date) | UNIX 时间戳 |
| UTC_DATE() | 返回 UTC 日期、时间 |
| MONTH(date), MONTHNAME(date) | 获取月份 |
| DAYNAME(d), DAYOFWEEK(d), WEEKDAY(d), WEEK(d), WEEKOFYEAR(d) | 获取星期 |
| DAYOFYEAR(d), DAYOFMONTH(d) | 获取天数 |
| QURTER(date), MINUTE(time), SECOND(time) | 获取年份、季度、小时、分钟、秒钟 |
| EXTRACT(type FROM d) | 获取日期的指定值 |
| TIME_TO_SEC(time), SEC_TO_TIME(seconds) | 时间和秒钟转换 |
| DATE_ADD(date, INTERVAL expr type), ADDDATE(date, INTERVAL expr type), DATE_SUB(date, INTERVAL expr type), SUBDATE(date, INTERVAL expr type), ADDTIME(date, expr), SUBTIME(date, expr) | 计算日期和时间 |
| DATE_FORMAT(date, format) | 将日期和时间格式式 |
# 条件判断函数
| 函数 | 作用 |
|---|---|
| IF(expr, v1, v2) | expr 为 TRUE 则返回 v1,否则为 v2 |
| IFNULL(v1, v2) | v1 若为 NULL 则返回 v2,否则返回 v1 |
| CASE | CASE expr WHEN v1 THEN r1 [WHEN v2 THEN r2] [ELSE rn] END CASE WHEN v1 THEN r1 [WHEN v2 THEN r2] [ELSE rn] END |
# 系统信息函数
| 函数 | 作用 |
|---|---|
| VERION() | 获取 MySQL 版本号 |
| CONNECTION_ID() | 获取连接数 |
| DATABASE(), SCHEMA() | 获取数据库名 |
| USER(), CURRENT_USER, CURRENT_USER(), SYSTEM_USER(), SESSION_USER() | 获取用户名 |
| CHARSET(str), COLLATION(str) | 获取字符串的字符集和排序方式 |
| LAST_INSERT_ID() | 获取最后一个自动生成的 ID 值 |
# 加密函数
| 函数 | 作用 |
|---|---|
| PASSWORD(str) | |
| MD5(str) | |
| ENCODE(str,pswd_str) | |
| DECODE(crypt_str,pswd_str) |
# 其他函数
| 函数 | 作用 |
|---|---|
| FORMAT(x,n) | 将数字 x 格式化并以四舍五入方式保留小数点后 n 位,结果以字符串形式返回 |
| CONV(n,from_base,to_base) | 不同进制数字转换 |
| INET_ATON(expr),INET_NTOA(expr) | IP 地址与数字互转 |
| GET_LOCK(str,timeout),RELEASE_LOCK(str),IS_FREE_LOCK(str),IS_USED_LOCK(str) | 加锁和解锁 |
| BENCHMARK(count,expr) | 重复执行指定操作 |
| CONVERT(... USING ...) | 改变字符集 |
| CASE(x,AS type), CONVERT(x,type) | 改变数据类型,可转换的 type 有:BINARY, CHAR(N), DATE, TIME, DATETIME, DECIMAL, SIGNED, UNSIGNED |
# DQL
SELECT 字段名1,字段名2,...字段名n FROM 表名 WHERE 查询条件;
/*
查询条件
IN, BETWEEN AND
LIKE: %, _
IS NULL
AND, OR
去重
DISTINCT
排序
ORDER BY 字段名 DESC/ASC LIMIT offset,n
分组
GROUP BY 字段 HAVING 条件表达式
WITH ROLLUP?
聚合函数
COUNT()
SUM()
AVG()
MAX()
MIN()
*/
/*
连接查询
INNER JOIN
LEFT JOIN, RIGHT JOIN
子查询
ANY, SOME, ALL
EXISTS
IN
比较运算符
合并查询结果
UNION [ALL]
*/
/*
别名 AS
表别名
字段别名
*/
/*
正则表达式
^d 以 d 为开头
x$ 以 x 为结尾
., *, +, [], [^], {M}, {M,N}, {M,}, |
*/
# DML
# 插入数据
INSERT INTO table_name(column_list) VALUES(value_list);
INSERT INTO table_name(column_list) VALUES(value_list1),(value_list2),...,(value_listn);
INSERT INTO table_name1(column_list1) SELECT (column_list2) FROM table_name2 WHERE (condition);
# 更新数据
UPDATE table_name SET column_name1 = value1, ..., column_namen = valuen WHERE (condition);
# 删除数据
DELETE FROM table_name WHERE (condition);
# 索引
# 索引分类
- 普通索引和唯一索引
- 单列索引和组合索引
- 全文索引
- 空间索引
# 索引设计原则
- 索引并非越多越好
- 避免对经常更新的表进行过多的索引,并且索引中的列尽可能少
- 数据量小的表最好不要使用索引
- 在条件表达式中经常用到的不同值较多的列上建立索引,在不同值少的列上不要建立索引
- 当唯一性是某种数据本身的特征时,指定唯一索引
- 在频繁进行排序或分组(即进行 group by 或 order by 操作)的列上建立索引
# 索引操作
# 创建索引
CREATE TABLE table_name [col_name data_type]
[UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] [index_name] (col_name [length]) [ASC|DESC]
ALTER TABLE ADD ...
CREATE INDEX ...
# 删除索引
ALTER TABLE table_name DROP INDEX index_name;
DROP INDEX index_name ON table_name;
# 存储过程和函数
# 创建存储过程
CREATE PROCEDURE sp_name([proc_parameter])[characteristics...]
rountine_body
# 创存储函数
CREATE FUNCTION func_name([func_parameter]) RETURNS type [characteristics...]
rountine_body
# 变量的使用
## 定义变量
DECLARE var_name [,var_name...] data_type [DEFAULT value];
## 为变量赋值
SET var_name = expr [,var_name = expr...];
## 定义条件和处理程序
# 光标的使用
## 声明光标
## 打开光标
## 使用光标
## 关闭光标
# 流程控制的使用
## IF 语句
## CASE 语句
## LOOP 语句
## LEAVE 语句
## ITERATE 语句
## REPEAT 语句
## WHILE 语句
# 调用存储过程和函数
CALL sp_name([parameter[,...]])
# 查看存储过程和函数
SHOW PROCEDURE STATUS;
SHOW FUNCTION STATUS;
SHOW CREATE PROCEDURE sp_name;
SHOW CREATE FUNCTION sp_name;
SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME = 'sp_name';
# 修改存储过程和函数
ALTER {PROCEDURE|FUNCTION} sp_name [characteristic ...]
# 删除存储过程和函数
DROP {PROCEDURE|FUNCTION} [IF EXISTS] sp_name;
# 视图
# 创建视图
CREATE [OR REPLACE] [ALGORITHM={UNDEFINED|MERGE|TEMPTABLE}] VIEW view_name [(column_list)]
AS SELECT _statement [WITH [CASCADED|LOCAL] CHECK OPTION]
# 查看视图
DESCRIBE 视图;
SHOW TABLE STATUS LIKE '视图名';
SHOW CREATE VIEW 视图名;
SELECT * FROM information"_schema.views;
# 修改视图
CREATE [OR REPLACE] [ALGORITHM={UNDEFINED|MERGE|TEMPTABLE}] VIEW view_name [(column_list)]
AS SELECT _statement [WITH [CASCADED|LOCAL] CHECK OPTION]
ALTER [ALGORITHM={UNDEFINED|MERGE|TEMPTABLE}] VIEW view_name [(column_list)]
AS SELECT _statement [WITH [CASCADED|LOCAL] CHECK OPTION]
# 删除视图
DROP VIEW [IF EXISTS] view_name [,view_name] ... [RESTRICT|CASCADE]
# 触发器
# 创建触发器
CREATE TRIGGER trigger_name trigger_time trigger_event ON tbl_name FOR EACH ROW trigger_stmt;
# 查看触发器
SHOW TRIGGERS;
SELECT * FROM information_schema.triggers WHERE conditon;
# 删除触发器
DROP TRIGGER 【schema_name.]trigger_name;
# DCL(用户管理)
- 权限表
- user 表
- db 表和 host 表
- tables_priv 表和 columns_priv 表
- procs_priv 表
- 账户管理
# 新建用户
CREATE USER ...
GRANT ...
直接操作权限表
# 删除普通用户
DROP USER ...
DELETE ...
# root 用户修改自己密码
mysqladmin ...
修改 user 表
SET ...
# root 用户修改普通用户密码
SET ...
UPDATE ...
GRANT ...
# 普通用户修改密码
SET PASSWORD = PASSWORD('newpassword');
# root 用户密码丢失的解决办法
使用 --skip-grant-tables 选项启动
使用 root 用户登录和重新设置密码
加载权限表
权限管理
- MySQL 各种权限
- 授权
- 收回权限
- 查看权限
SHOW GRANTS FOR 'user'@'host';访问控制
- 连接核实阶段
- 请求核实阶段

# 备份和还原
# 数据备份
- 使用 mysqldump 命令备份
mysqldump -u user -h host -ppassword dbname[tbname,[tbname...]] >filename.sql
- 直接复制整个数据库目录(InnoDB 存储引擎的表不适用,不同的版本可能不兼容)
- 使用 mysqlhotcopy 工具快速备份(只可以备份 MyISAM 类型的表)
# 数据还原
- 使用 mysql 命令还原
- 直接复制到数据库目录(复制后需要调整文件的所有者)
- mysqlhotcopy 快速恢复
# 数据库迁移
- 相同版本 MySQL
mysqldump -h www.bac.com -uroot -ppassword dbname|mysql -h www.bcd.com -uroot -ppassword
- 不同版本 MySQL
- 不同数据库之间(如 MySQL -> Oracle, MySQL -> SQL Server
# 表的导出和导入
# 导出
- SELECT ... INTO OUTFILE 语句
SELECT columnlist FROM table WHERE condition INTO OUTIFLE 'filename' [OPTIONS]
- mysqldump 命令
mysqldump -T path -u root -p dbname [tables] [OPTIONS]
- mysql 命令
mysql -u root -p --execute="SELECT 语句" dbname > filename.txt
# 导入
- LOAD DATA INFILE ... 导入
LOAD DATA INFILE 'filename.txt' INTO TABLE tablename [OPTIONS] [IGNORE number LINES]
- mysqlimport 命令
mysqlimport -u root -p dbname filename.txt [OPTIONS]
# 日志
# 二进制日志
# 在 my.ini 开启
[mysqld]
log-bin [=path/[filename]]
expire_logs_days = 10
max_binlog_size = 100M
# 查看
mysql>show binary logs 查看文件个数及其文件名
mysqlbinlog 查看内容
# 删除
mysql>RESET MASTER 删除所有
mysql>PURGE MASTER LOGS 删除指定
# 使用二进制日志还原数据库
# 暂停
mysql>SET sql_log_bin = 0;
# 恢复
mysql>SET sql_log_bin = 1;
# 错误日志
# 开启
my.ini 中若没有指定则文件名默认为 hostname.err
[mysqld]
log-error = [path/[filename]]
# 查看
mysql>SHOW VARIABLES LIKE 'log_error';
# 删除
mysqladmin -u root -p flush-logs
# 通过查询日志
# 开启
my.ini
[mysqld]
log[=path/[filename]]
# 查看(直接使用文本编辑器)
# 删除
mysqladmin -u root -p flush-logs
# 慢查询日志
# 在配置中开启,或在 MySQL 服务启动时使用 --log-show-queries[=file_name] 开启
my.ini
[mysqld]
log-show-queries[=path/[filename]]
# 查看(直接使用文本编辑器)
# 删除
mysqladmin -u root -p flush-logs
flush logs
# 性能优化
优化查询
- 分析查询语句
EXPLAIN [EXTENDED] SELECT select_options; DESCRIBE SELECT select_options;- 索引对查询速度的影响
- 使用索引查询:LIKE, OR, 多列索引的查询问题
- 优化子查询:使用连接(JOIN)来替代子查询,连接查询不需要建立临时表
优化数据库结构
- 将字段很多的表分解成多个表
- 增加中间表
- 增加冗余字段
- 优化插入记录的速度
- 禁用索引
- 禁用唯一性检查
- 使用批量插入
- 使用 LOAD DATA INFILE 批量导入
- 分析表、检查表和优化表
- 分析关键字的分布
- 检查表是否存在错误
- 消除删除或更新造成的空间浪费
优化 MySQL 服务器
- 优化 MySQL 的参数:key_buffer_size, table_cache, query_cache_size
- 优化服务器硬件
# 主从复制

# 读写分离——MySQL Proxy
# MySQL Cluster
# MySQL Workbench 的使用
# MySQL Utilites 的使用
- mysqldbcompare 比较数据
- mysqldbcopy 复制数据
- mysqldbexport 导出数据
- mysqldbimport 导入数据
- mysqldiff 比较对象的定义
# PHP 操作 MySQL 数据库
- mysqli 类库
- mysqli_connect()
- mysqli_select_db()
- mysqli_query()
- mysqli_fetch_assoc()
- mysqli_fetch_object()
- mysqli_num_rows()
- mysqli_free_result()
- mysqli_close()
# 编辑记录
01-20-2018 13:22 周日