MySql 入门
数据库(database)就是存储数据的仓库。为了方便数据的存储和管理,将数据按照特定的规律在磁盘上,通过数据库管理系统,有效地组织和管理存储在数据库中的数据。
数据库系统和数据库不是一个概念,数据库系统(DBS),比数据库大很多,由数据库、数据库管理系统,应用开发工具构成。
数据库管理系统(DataBase Management System,简称 DBMS),是用来定义数据,管理和维护数据的软件。它是数据库系统的一种重要组成部分。
常见的数据库系统:甲骨文Oracle数据库,IBM的DB2,微软SQL Server、Access,PostgreSql、MySQL。
MySql 数据库
MySQL数据库特点:开放源代码的数据库,MySQL的跨平台性(Unix、Linux、Windows等),开源免费,功能强大使用方便。
SQL:(Structured Query Language),结构化查询语句,数据库管理系统通过 SQL 语言来管理数据库中的数据。
SQL 语言组成部分:
- DDL(Data Defination Language),数据定义语言,主要用于定义数据库、表、数据、索引和触发器等,像 DROP、CREATE、ALTER 等语句。
- DML(Data Manipulation Language),主要包括对数据的增删改。INSERT 插入数据、UPDATA 更新数据、DELETE 删除数据。
- DQL(Data Query Language),数据检索语句,用来从表中获得数据,确定数据怎样在应用程序中给出,像 SELECT 查询数据。
- DCL(Data Control Language),数据控制语言,主要用于控制用户的访问权限,像 GRANT、REVOKE、COMMIT、ROLLBACK 等语句。
安装与配置
官网下载 有两个版本,一个是二进制分发版(.msi 安装文件),一个是 免安装版(.zip 压缩文件)。二进制分发版和安装普通软件一样的,在选择需要安装的文件时,如果只是学习 MySql,可以只选择安装 MySQL Server。默认安装路径是:C:\Program Files\MySQL\MySQL Server 5.6
。8.x 版本的压缩包版本没有 .ini 文件,和 5.x 版本的不一样,配置方式也不一样,以下内容以 5.x 版本为例。
目录 | 备注 | ||
---|---|---|---|
bin目录 | 存储可执行文件 | ||
data 目录 | 存储数据文件 | ||
include 目录 | 存储包含的头文件 | ||
lib 目录 | 存储库文件 | ||
docs 目录 | 文档 | ||
share 目录 | 错误信息和字符集文字 | ||
my.ini文件 | MySQL的配置文件,默认的是 my-default.ini,需要复制并重命名为 my.ini | 设置字符集 | 客户端字符集[mysql]:default-character-set=utf8 |
服务器端字符集[masqld]:character-set-server=utf8 |
运行 MySql 的步骤:
- 配置环境变量,在 Path 中添加一条数据,即 MySql 的 bin 目录,
C:\Program Files\MySQL\MySQL Server 5.6\bin
- 开启 MySql 服务,安装的时候默认会添加一个名为
MySQL56
的服务,开启服务有两个方式,一是打开系统的服务,手动开启;二是在控制台输入:net start mysql56
,关闭服务是:net stop mysql56
- 配置编码字符集,避免显示乱码。需要在 my.ini 中添加两行:客户端[mysql]
default-character-set=utf8
,服务器端[mysqld]character-set-server=utf8
- 连接 MySql,需要在控制台输入:
mysql -u root -p
登录与退出
登录命名:mysql [参数][参数值]
,比如 mysql -uroot -p
。
常用参数 | 备注 |
---|---|
-u | 用户名 |
-p | 密码 |
-h | 服务器名称,-h localhost ,-h 127.0.0.1 |
-P | 端口号,默认安装端口号 3306 |
-D,--database=name | 打开指定数据库 |
--prompt=name | 设置命令提示符,--prompt=>>> ,登录之后也可以设置,prompt \h~\u~\D~\d ,服务器名称当前用户名完整的日期~当前数据库 |
--delimiter=name | 指定分隔符,登录之后也可以修改,DELIMITER //,输入语句后以// 结束,默认分隔符; 、\g |
-V,--version | 输出版本信息并且退出 |
退出命名:exit
| quit
| \q
扩展语句:
- SELECT VERSION(); select v()\g 查看当前数据库版本号,
\g
等同于;
- SELECT USER(); 查看当前用户
- SELECT NOW(); 查看当前时间
- SELECT VERSION()\c 不会执行这个命令
- \T C:\Develop\mysql1.txt 输出日志文件到 mysql1.txt ,结束日志
\t
- SHOW WARNINGS; 查看语句的警告
- SELECT {DATABASE() | SCHEMA()} :得到当前打开的数据库名称
- help [要查询的内容],比如 help CREATE DATABASE
数据库操作(DDL)
MySql 语句规范:
- 关键字与函数名称全部大写
- 数据库名称、表名称、字段名称等全部小写
- SQL语句必须以分隔号结尾(或\g)
- SQL语句支持折行操作,只要不把单词、标记或引号字符串分割为两部分,可以在下一行继续写
- 数据库名称、表名称、字段名称等尽量不要使用MySQL的保留字,如果需要使用的时候需要用反引号(``)将名称括起来
1.创建数据库,数据库保存在 data 文件夹中
CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name [[DEFAULT] CHARACTER SET [=] charset_name]
数据库名称:DATABASE 或 SCHEMA;{ }
代表必须要出现的,[ ]
代表可以选的;
db_name表示数据库名称;
CHARACTER SET [=] charset_name 表示编码方式,如 utf8
2.查看当前服务器下的数据库列表:SHOW {DATABASES | SCHEMAS}
3.查看制定数据库的定义:SHOW CREATE {DATABASE | SCHEMA} db_name
4.修改制定数据库的编码方式:ALTER {DATABASE | SCHEMA} db_name [DEFAULT] CHARACTER SET [=] character_name
5.打开指定数据库:USE db_name
6.删除指定数据库:DROP {DATABASE | SCHEMA} [IF EXISTS] db_name
数据表相关操作
数据表:
- 是数据库最重要的组成部分之一,是其他对象的基础
- 是存储数据的数据结构
- 是包含了特定实体类型的数据
- 由行(row)和列(column)构成的二维网络
- 一定先有表结构,再有数据
- 至少有一列,可以没有行或者多列
- 数据表名称要求唯一,而且不要包含特殊字符
创建数据表
CREATE TABLE [IF NOT EXISTS] tbl_name(
字段名称 字段类型 [完整性约束条件]
...
)ENGINE=引擎名称 CHARSET='编码方式';
CREATE TABLE [IF NOT EXISTS] tbl_name(
字段名称 字段类型 [UNSIGNED | ZEROFILL] [NOT NULL] [DEFAULT 默认值] [[PRIMARY] KEY] [UNIQUE [KEY]]
)ENGINE=INNODB CHARSET=UTF8 AUTO_INCREMENT=数值;
CREATE TABLE IF NOT EXISTS `user`(
id SMALLINT,
username VARCHAR(20),
age TINYINT,
sex ENUM('男','女','保密'),
email VARCHAR(50),
addr VARCHAR(20),
birth YEAR,
salary FLOAT(8,2),
tel INT,
# COMMENT 是给字段添加注释
married TINYINT(1) COMMENT '0代表未结婚,非0代表结婚'
)ENGINE=INNODB CHARSET=UTF8;
注释:# 注释内容 或者 -- 注释内容
完整性约束条件:
- PRIMARY KEY 主键
- AUTO_INCREMENT 自增
- FOREIGN KEY 外键
- NOT NULL 非空
- UNIQUE KEY 唯一
- DEFAULT 默认值
- ZEROFILL 零填充
- UNSIGNED 无符号
字段类型:查看数据类型help [数据类型]
或\h [数据类型]
-
整数类型:
- TINYINT :长度 1 字节,有符号值 -128 到 127(-2^7 到 2^7 - 1),无符号 0 - 255(2^8 - 1)
- SMALLINT :2 字节
- MEDIUMINT : 3 字节
- INT :4 字节
- BIGINT :8 字节
- BOOL,BOOLEAN :1 字节,等价于 TINYINT(1) ,0 为 false,其余为 true
-
浮点类型:
- FLOAT[(M, D)] :4 字节,负数取值范围为 -3.40E+38 到 -1.17E-38、0 和 1.175E-38 到 3.40E+38,M 是数字总位数,D 是小数点后面的位数。如果 M 和 D 被省略,根据硬件允许的限制类保存值。单精度浮点数精度大约 7 位小数位。
- DOUBLE[(M, D)] :8 字节
- DECIMAL[(M, D)] : M+2 字节,和 DOUBLE 一样,
内部以字符串形式存储数值
-
字符串类型:
- CHAR(M) :M 个字节,0<=M<=255,CHAR 在保存的时候,前面会用空格填充到指定的长度,在检索的时候后面的空格会去掉
- VARCHAR(M) : L+1 个字节,其中 L<=M 且 0<=M<=65535,L 为长度,VARCHAR在保存的时候,不进行填充。当值保存和检索时尾部的空格仍保留
- TINYTEXT :L+1 字节,其中 L<2^8
- TEXT : L+2 字节,其中 L<2^16,只能保存字符数据,而且不能有默认值
- MEDIUMTEXT :L+3 字节
- LONGTEXT :L+4 字节
- ENUM('value1', 'value2', ...) :1 或 2 个字节,取决于枚举值的个数(最多 65535 个值)
- SET('value1', 'value2', ...) :1、2、3、4 或 8 个字节,取决于 set 成员的数目(最多 64 个成员)
-
日期时间类型:
- TIME :3 字节
- DATE :3 字节,1000-01-01 ~ 9999-12-31
- DATETIME :8 字节,1000-01-01 00:00:00
- TIMESTAMP :4字节,1970-01-01 00:00:01 UTC ~ 2038-01-19 03:14:07,一般用整型保存时间戳
- YEAR : 1 字节,1901 - 2155
- 标准时间转为时间戳: $dateline=strtotime($nowtime);
- 时间戳转为标准时间:$nowtime=date('H:i:s',$dateline);
存储引擎
存储引擎就是指表的类型。数据库的存储类型决定了表在计算机中的存储方式。用户可以根据不同的存储方式,是否进行事务处理等来选择合适的存储引擎。
查看数据库的存储引擎:
- 查看支持的存储引擎:
SHOW ENGINES; 或者 SHOW ENGINES\G
- 查看显示支持的存储引擎信息:
SHOW VARIABLES LIKE 'have%'
- 查看默认的存储引擎:
SHOW VARIABLES LIKE 'storage_engine'
常用存储引擎及特点:
- InnoDB :事务,回滚,多版本并发控制,支持外键约束,表结构存储在 .frm 文件内
- MyISAM :保存到三个文件中,.frm .MYD .MYI,
- MEMORY :存储到内存中,hash 索引
查看数据表
1.查看数据库下的数据表:SHOW TABLES
2.查看指定表的表结构:DESC tbl_name, DESCRIBE tbl_name, SHOW COLUMNS FROM tbl_name
3.查看创建表的定义:SHOW CREATE TABLE tbl_name;
修改数据表
1.修改表名:ALTER TABLE tbl_name RENAME [TO | AS] new_name 或者 RENAME TABLE tbl_name TO new_name
2.添加字段:ALTER TABLE tbl_name ADD 字段名称 字段类型 [完整性约束条件] [FIRST | AFTER 字段名称]
3.删除字段:ALTER TABLE tbl_name DROP 字段名称,或者 ALTER TABLE tbl_name DROP 字段1,DROP 字段2,...;
4.修改字段:ALTER TABLE tbl_name MODIFY 字段名称 [完整性约束条件] [FIRST | AFTER 字段名称] ,主键有自增长不能直接删除主键,需要先去掉自增长,修改字段可以去掉自增长
5.修改字段名称:ALTER TABLE tbl_name CHANGE 旧字段名称 新字段名称 字段类型 [完整性约束条件] [FIRST | AFTER 字段名称]
6.添加删除默认值:ALTER TABLE tbl_name ALTER 字段名称 SET DEFAULT 默认值 , ALTER TABLE tbl_name ALTER 字段名称 DROP DEFAULT
7.添加主键:ALTER TABLE tbl_name ADD [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (字段名称, ...)
8.删除主键:ALTER TABLE tbl_name DROP PRIMARY KEY;
9.添加唯一:ALTER TABLE tbl_name ADD [CONSTRAINT [symbol]] UNIQUE [INDEX | KEY] [索引名称](字段名称, ...) ,索引名称不能带有单引号,可以使用反引号。
10.删除唯一:ALTER TABLE tbl_name DROP {INDEX | KEY} index_name
11.修改表的存储引擎:ALTER TABLE tbl_name ENGINE=存储引擎名称
12.设置自增长的值:ALTER TABLE tbl_name AUTO_INCREMENT=值
13.删除数据表:DROP TABLE [IF EXISTS] tbl_name[, tbl_name...]
数据的操作(DML)
1.插入数据:
- 不指定具体的字段名:INSERT [INTO] tbl_name VALUES|VALUE(值,...)
- 列出指定字段:INSERT [INTO] tbl_name(字段名称1, ...) VALUES|VALUE(值1,...)
- 同时插入多条记录:INSERT [INTO] tbl_name[(字段名称 ...)] VALUES(值 ...), (值 ...)...
- 通过 SET 形式插入记录:INSERT [INTO] tnl_name SET 字段名称=值,...
- 将查询结果插入到表中:INSERT [INTO] tbl_name[(字段名称, ...)] SELECT 字段名称 FROM tbl_name [WHERE 条件]
2.更新数据:UPDATE tbl_name SET 字段名称=值,... [WHERE 条件] [ORDER BY 字段名称] [LIMIT 限制条数]
- LIMIT 限制条数只能有一个数,不能由两个数包含偏移量
3.删除数据:
- DELETE FROM tbl_name [WHERE 条件] [ORDER BY 字段名称] [LIMIT 条数],没有条件会删除所有记录,但是
DELETE删除不会重置AUTO_INCREMENT的值
- LIMIT 条数只能有一个数,不能包含偏移量
彻底清空数据表
: TRUNCATE [TABLE] tbl_name;
查询数据操作(DQL)
普通查询
1.查询记录:
SELECT select_expr[,select_expr...]
[
FROM table_references
[WHERE 条件]
[GROUP BY {col_name | position} [ASC | DESC],...分组]
[HAVING 条件 对分组结果进行二次筛选]
[ORDER BY {col_name | position} [ASC | DESC],...排序]
[LIMIT 限制显示条数]
]
2.查询表达式:
- 每个表达式表示想要的一列,必须至少有一列,多个列之间以逗号分隔
*
表示所有列,tbl_name.*
表示命名表的所有列,tb_name.tbl_name.*
表示哪个数据库中的哪个表里的所有列- 查询表达式可以使用
[AS]alias_name
为表赋予别名
3.WHERE 条件:
查询条件 | 符号 |
---|---|
比较 | = 、< 、<= 、> 、>= 、!= 、<> 、!> 、!< 、<=> (可以判断是不是 NULL) |
指定范围 | BETWEEN AND 、NOT BETWEEN AND |
指定集合 | IN 、 NOT IN |
匹配字符 | LIKE 、 NOT LIKE (模糊查询,% 代表0个一个或者多个任意字符,_ 代表1个任意字符) |
是否为空值 | IS NULL 、 IS NOT NULL |
多个查询条件 | AND 、 OR |
4.GROUP BY 查询结果分组
- SELECT * FROM tbl_name GROUP BY 字段1,字段2... :先按照 字段1 分组,分完组之后再按照 字段2 分组
- 配合 GROUP_CONCAT() 得到分组详情 --- 默认下获取的分组是不全的,只能看到组里的一条记录
- SELECT id,sex,GROUP_CONCAT(username) FROM cms_user GROUP BY sex;
- 配合聚合函数:
- COUNT() ,COUNT(字段) 不统计 NULL 值,COUNT(*)就能统计技术
- MAX()
- AVG()
- SUM()
- 配合 WITH ROLLUP 记录上面所有记录的总和,会在查询到的数据中增加一行数据
- SELECT * FROM tbl_name GROUP BY 字段名称 WITH ROLLUP
5.HAVING 子句
通过 HAVING 子句对分组结果进行二次筛选,和 WHERE 差不多,只能用于分组之后进行筛选。SELECT * FROM tbl_name GROUP BY 字段名称 HAVING 条件1 [[AND | OR...] 条件2]
如果没有 GROUP BY 进行分组,结果可能和 WHERE 一样的。
6.ORDER BY 排序
ORDER BY 对查询结果进行排序,默认排序是 ASC 升序排序,DESC 是降序排列。SELECT * FROM tbl_name ORDER BY 字段名称 [ASC|DESC]
SELECT * FROM tbl_name ORDER BY RAND(); 随机数排序
7.LIMIT 限制查询结果显示条数
对查询结果,限制显示条数,SELECT * FROM tbl_name LIMIT 条数
SELECT * FROM tbl_name LIMIT 起始条数偏移量(以0开始), 每页显示条数
连接查询
连接查询
是将两个或两个以上的表按某个条件连接起来,从中选取需要的数据。连接查询是同时查询两个或两个以上的表时使用的,当不同的表中存在相同意义的字段时,可以通过该字段连接这几个表。
SELECT cms_user.id,username,proName FROM cms_user,provinces
WHERE cms_user.proId=provinces.id;
SELECT u.id,u.username,u.email,u.sex,p.proName
FROM cms_user AS u
INNER JOIN provinces AS p
ON u.proId=p.id;
SELECT u.id,u.username,u.regTime,a.proName,u.sex,COUNT(*) AS totalUsers,GROUP_CONCAT(username)
FROM cms_user AS u
LEFT JOIN
provinces AS a
ON u.proId=a.id
WHERE sex='女'
GROUP BY a.proName
HAVING COUNT(*)>=1
ORDER BY u.id DESC
LIMIT 0,2;
1.内连接查询:
- JOIN|CROSS JOIN 、INNER JOIN
- 通过 ON 连接条件
- 显示两个表中符合连接条件的记录
2.外连接查询
- 左外连接: LEFT [OUTER] JOIN ,显示左表的全部记录及右表符合连接条件的记录
- 右外连接: RIGHT [OUTER] JOIN ,显示右表的全部记录以及左表符合条件的记录
3.外键
外键是表的一个特殊字段。被参照的表是主表,外键所在字段的表为子表。设置外键的原则:就是依赖于数据库中已存在的表的主键。外键的作用是建立该表与其父表的关联关系。父表中对记录做操作时,子表中与之对应的信息也应有相应的改变。
外键的作用保持数据的一致性和完整性;可以实现一对一或一对多的关系。
注意:
- 父表和子表必须使用相同的存储引擎,而且禁止使用临时表;
- 数据表的存储引擎只能为InnoDB;
- 外键列和参照列必须具有相似的数据类型。其中数字的长度或是否有符号位必需相同;而字符的长度则可以不同;
- 外键列和参照列必须创建索引。如果外键列不存在索引的话,MYSQL将自动创建索引。
外键约束的参照操作:
- CASCADE : 从父表删除或更新且自动删除或更新子表中匹配的行;
CONSTRAINT 父表_fk_子表 FOREIGN KEY(连接子表字段名称) REFERENCES 父表名(连接父表字段名称) ON DELETE CASCADE ON UPDATE CASCADE;
- SET NULL : 从父表删除或更新行,并设置子表中的外键列为NULL,如果使用该选项,必须保证子表列没有指定NOT NULL。
CONSTRAINT 父表_fk_子表 FOREIGN KEY(连接子表字段名称) REFERENCES 父表名(连接父表字段名称) ON DELETE SET NULL ON UPDATE SET NULL;
- RESTRICT : 拒绝对父表的删除或更新操作。
- NO ACTION : 标准SQL的关键字,在MySQL中与RESTRICT相同。
在连接查询中,如果一个字段在父表和子表中有关联,则不能直接用DELETE FROM tbl_name [ WHERE 条件 ]去删除父表中的字段(因为子表还会存在该字段),所以为了彻底删除,此时需要给子表创建一个外键,当需要删除一个字段时,必需先删除子表中的字段才能删除父表中的字段。
CREATE TABLE IF NOT EXISTS department(
id TINYINT AUTO_INCREMENT KEY,
dep VARCHAR(20) NOT NULL UNIQUE
)ENGINE=INNODB;
CREATE TABLE IF NOT EXISTS employee(
id SMALLINT AUTO_INCREMENT KEY,
username VARCHAR(20) NOT NULL,
depId TINYINT,
CONSTRAINT em_fk_dep FOREIGN KEY(depId) REFERENCES department(id)
)ENGINE=INNODB;
4.联合查询:查询的数目要一致
- UNION :SELECT username FROM tbl_name1 UNION SELECT username FROM tbl_name2;
- UNION ALL :SELECT username FROM tbl_name1 UNION ALL SELECT username FROM tbl_name2;
- 区别: UNION 去掉相同记录,UNION ALL 是简单的合并
子查询
子查询是将一个查询语句嵌套在另一个查询语句中。内层查询语句的查询结果,可以为外层查询语句提供条件。由内向外执行
引发子查询的情况:
- 使用 [NOT] IN 的字查询
- 使用比较运算符的子查询:=、>、<、>=、<=、<>、!=、<=>
- 使用 [NOT] EXISTS 的子查询,SELCT * FROM tbl_name WHERE EXISTS(SELECT ...) 条件是真才会有结果
- 使用 ANY | SOME 或者 ALL 的子查询
运算符 | ANY | SOME | ALL |
---|---|---|---|
>、>= | 最小值 | 最小值 | 最大值 |
<、<= | 最大值 | 最大值 | 最小值 |
= | 任意值 | 任意值 | |
<>、!= | 任意值 |
将查询结果写入到数据表:
-- 向已经存在的表中插入数据
INSERT [INTO] tbl_name [(col_name,...)] SELECT ...
INSERT employee(username)
SELECT username FROM department
-- 在存储过程中向变量插入数据
SELECT value1 INTO var_anem FROM tbl_name
创建数据表同时将查询结果写入到数据表:
CREATE TABLE [IF NOT EXISTS] tbl_name[(create_definition,...)] select_statement
CREATE TABLE test(
id TINYINT UNSIGNED AUTO_INCREMENT KEY,
num TINYINT UNSIGNED
)SELECT id,score FROM student;
正则表达式查询
1.REGEXP '匹配模式'
SELECT * FROM cms_user WHERE username REGEXP '^A';
SELECT * FROM cms_user WHERE username REGEXP '[^ABC]';
2.常用匹配方式
模式字符 | 含义 |
---|---|
^ | 匹配字符开始的部分 |
$ | 匹配字符串结尾部分 |
. | 代表字符串中的任意一个字符,包括回车和换行,相当于 LIKE 语句中的_ |
[字符集合] | 匹配字符集合中的任何一个字符 |
[^字符集合] | 匹配除了字符集合以外的任何一个字符 |
s1 | s2 |
* | 代表0个1个或者多个其前的字符,相当于 LIKE 语句中的 % |
+ | 代表1个或者多个其前的字符 |
String{N} | 字符串出现 N 次 |
字符串{M, N} | 字符串至少出现 M 次,最多 N 次 |
运算符和函数
运算符
1.算数运算符:SELECT 3/0;
符号 | 表达式 | 作用 |
---|---|---|
+ | X1+X2 | 加法 |
- | X1-X2 | 减法 |
* | X1*X2 | 乘法 |
/ | X1/X2 | 除法 |
DIV | X1 DIV X2 | 除法 |
% | X1 % X2 | 取余 |
MOD | MOD(X1,X2) | 取余 |
2.比较运算符:结果只能为真或假,1为真,0为假
符号 | 形式 | 作用 |
---|---|---|
= | X1=X2 | 判断是否相等 |
<>或!= | X1<>X2或 X1!=X2 | 判断是否不相等 |
<=> | X1<=>X2 | 判断是否相等,可以判断是否等于NULL |
>、>= | X1>X2或 X1>=X2 | 判断是否大于等于 |
<、<= | X1判断是否小于等于 |
|
IS NULL或IS NOT NULL | X1 IS NULL 或 X1 IS NOT NULL | 判断是否等于NULL |
BETWEEN AND或NOT BETWEEN AND | X1 BETWEEN m AND n | 判断是否在范围内 |
IN 或 NOT IN | X1 IN(值,...) | 判断是否在某一固定范围内 |
LIKE 或 NOT LIKE | X1 LIKE 表达式 | 判断是否撇配 |
REGEXP | REGEXP 正则表达式 | 判断是否正则匹配 |
3.逻辑运算符
符号 | 形式 | 作用 |
---|---|---|
&&或者AND | 与 | 并且 |
或者OR | ||
!或者NOT | 非 | 取反 |
XOR | 异或 | 不同为真 |
4.运算符的优先级:通过括号()改变优先级
优先级 | 运算符 | 优先级 | 运算符 |
---|---|---|---|
1 | ! | 8 | |
2 | ~ | 9 | =、<=>、<、<=、>、>=、!=、<>、IN、IS NULL、LIKE、REGEXP |
3 | ^ | 10 | BETWEEN AND、CASE、WHEN、THEN、ELSE |
4 | *、/、DIV、%、MOD | 11 | NOT |
5 | +、- | 12 | &&、AND |
6 | >>、<< | 13 | |
7 | & | 14 | ;= |
函数
1.数学函数
名称 | 描述 |
---|---|
CEIL() | 进一取整 |
MOD | 取余数(取模) |
ROUND() | 四舍五入,SELECT ROUND(3.123,2); 3.12 |
ABS() | 取绝对值 |
FLOOR() | 舍一取整 |
POWER(X,n) | 幂运算 |
TRUNCATE() | 数字截取,SELECT TRUNCATE(43.125,1); 43.1 |
PI() | 圆周率 |
RAND()和RAND(X) | 返回0~1之间的随机数,RAND(X),X相同时返回的随机数相同 |
SIGN(X) | 返回X的符号,X为负数、0、正数,分别返回-1和0和1 |
EXP(X) | 计算e的几次方 |
2.字符串函数
名称 | 描述 |
---|---|
CHAR_LENGTH (S) | 返回字符串的字符数 |
LENGTH | 返回字符串的长度 |
CONCAT (S1,S2,...) | 将字符串合并为一个字符串 |
CONCAT_WS (X,S1,S2,...) | 以指定分隔符连接字符串 |
UPPER (S) /UCASE (S) | 将字符串转换为大写 |
LOWER (S) /LCASE (S) | 将字符串转换为小写 |
LEFT(S,N) /RIGHT(S,N) | 返回字符串的前/后n个字符 |
LPAD (S1,LEN,S2) /RPAD (S1,LEN,S2) | 将字符串S1用S2填充到指定的LEN |
LTRIM(S)/RTRIM(S)/TRIM(S) | 去掉字符串中的空格 |
TRIM(S1 FROM S) | 去掉字符串S中开始出现和结尾处的字符串S1 |
REPEAT(S,N) | 重复字符串指定次数 |
SPACE(N) | 返回N个空格 |
REPLACE(S,S1,S2) | 将字符串S中搜索S1替换成S2 ,会区分大小写 |
STRCMP(S1,S2) | 比较字符串,>=<分别返回1,0,-1 ,比较不会区分大小写 |
SUBSTRING(S,P,LEN) | 截取字符串,从第P个位置截取LEN个字符,包括截取字符 |
REVERSE(S) | 反转字符串 |
ELT(N,S1,S2) | 返回指定位置的字符串,字符串起始点从1开始 |
3.日期时间函数
名称 | 描述 |
---|---|
CURDATE(),CURRENT_DATE() | 返回当前日期 |
CURTIME(),CURRENT_TIME() | 返回当前时间 |
NOW() | 返回当前日期和时间 |
MONTH(D) | 返回日期中月份的值 *MONTH(NOW()) |
MONTHNAME(D) | 返回日期中月份名称,January *MONTHNAME(NOW()) |
DAYNAME(D) | 返回日期是几,Monday *MONTHNAME(NOW()) |
DAYOFWEEK(D) | 返回一周内的第几天,1代表星期日 *DAYOFWEEK(NOW()) |
WEEKDAY(D) | 返回日期是星期几,0代表是星期一 *WEEKDAY(NOW()) |
WEEK(D) | 一年中的第多少个星期 *WEEK(NOW()) |
YEAR(D) | 返回年份值 |
HOUR(T) | 返回小时值 |
MINUTE() | 返回分钟值 |
SECOND(T) | 返回秒数 |
DATEDIFF(D1,D2) | 计算两个日期之间的相隔的天数 |
4.条件判断函数
名称 | 描述 |
---|---|
IF(EXPR,V1,V2) | 如果表达式EXPR成立,返回结果v1;否则v2 |
IFNULL (V1,V2) *IFNULL间没有空格 | 如果v1的不为空,就显示v1的值;否则v2 |
CASE WHEN exp1 | CASE表示函数开始,END表示函数结束。 |
THEN v1[ WHEN exp2 | 如果exp1成立时,返回v1。如果表达式exp2成立时,返回v2值。 |
THEN v2 ] [ ELSE vn ] END | 依次类推,最后遇到ELSE时,返回vn的值 |
5.系统函数
名称 | 描述 |
---|---|
VERSION() | 返回数据库版本号 |
CONNECTION_ID() | 返回服务器的连接数 |
DATABASE(),SCHEMA() | 返回当前数据库名 |
USER(),SYSTEM_USER() | 返回当前用户 |
CURRENT_USER(),CURENT_USER | 返回当前用户 |
CHARSET(STR) | 返回字符串STR的字符集 |
COLLATION(STR) | 返回字符串STR的校验字符集 |
LAST_INSERT_ID() | 返回最近生成的AUTO_INCREMENT值 |
6.其他
名称 | 描述 |
---|---|
MD5(str) | 信息摘要算法 |
PASSWORD(str) | 密码算法 |
ENCODE(str,pwd,str) | |
DECODE(crypt_str,pwd_str) | 对通过ENCODE加密之后的内容解密 |
FORMAT(x,n) | 将数字x进行格式化,将x保留到小数点后n 位 |
ASCII(s) | 返回字符串s的第一个字符的ASCII码 |
BIN(x) | 返回x的二进制编码 |
HEX(x) | 返回x的十六进制编码 |
OCT(x) | 返回x的八进制编码 |
CONV(x,f1,f2) | 将x从f1进制数变成f2进制数 |
INET_ATON(IP) | 将IP地址转换成数字 |
INET_NTOA(n) | 将数字转换成IP地址 |
GET_LOCT(name,time) | 定义锁,IS_FREE_LOCK(name)判断是否使用锁,0表示存在锁,1表示不存在锁 |
RELEASE_LOCK(name) | 解锁 |
索引
索引由数据库中一列或多列组合而成,其作用是提高对表中数据的查询速度。优点是可以提高检索数据的速度,缺点是创建和维护索引需要耗费时间,索引可以提高查询速度,会减慢写入速度。
索引分类:
- 普通索引 :相当于书签
- 唯一索引 :UNIQUE KEY、PRIMARY KEY是一种特殊的唯一索引
- 全文索引 :用FULLTEXT,只能创建在CHAR、VARCHAR、text等字符字段上
- 单列索引 :在一个字段上创建索引
- 多列索引 :在多个字段上创建索引
- 空间索引 :搜索引擎为MyISAM ,数据类型GEOMETRY
创建索引
1.创建表的时候创建索引
CREATE TABLE tbl_name(
字段名称 字段类型 [完整性约束条件],
...,
[UNIQUE | FULLTEXT |SPATIAL] INDEX | KEY [索引名称](字段名称[(长度)]
[ASC | DESC])
);
2.在已经存在的表上创建索引
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX 索引名称 ON 表名{字段名称[(长度)] [ASC | DESC] }
ALTER TABLE tbl_name ADD [UNIQUE | FULLTEXT | SPATIAL] INDEX 索引名称(字段名称[(长度)] [ASC | DESC]);
删除索引
删除索引
DROP INDEX 索引名称 ON tbl_name;
ALTER TABLE tbl_name DROP INDEX 索引名称
MySql 编码设定 和 变量
编码设定
1.服务器编码设定:为解决客户端连接乱码net start mysql56
开启mysql服务,mysql -u root -h 127.0.0.1 -p root
打开mysql。
导入数据库:source 数据库所在路径.数据库名加后缀
,如 source C:/Develop/mysql/test.sql,\
变为/
。
查看数据库创建方式SHOW CREATE TABLE tbl_name
,如果编码方式是CHARSET=latin1
,在插入中文和在CMD上查看是可以看到,但在客户端连接工具中查看是乱码的。
打开命令窗口,SHOW VARIABLES LIKE 'CHAR%'
,查看客户端编码方式,如果不是utf8方式则进行修改。在my.ini文件中修改客户端编码 default-character-set=utf8 ,服务端编码 character-set-server=utf8 。
如果配置文件中修改了不能生效,则用下面的方法,但只在当前状态下有效,当重启数据库服务后失效
:
SET character_set_client = utf8;
SET character_set_connection = utf8;
SET character_set_database = utf8;
SET character_set_results = utf8;
SET character_set_server = utf8;
或 SET names 'utf8';
如果已经修改了my.ini,重启了服务还是不能生效,可以查看服务可执行文件的路径
:
"C:\Program Files\MySQL\MySQL Server 5.6\bin\mysqld.exe" --defaults-file="C:\ProgramData\MySQL\MySQL Server 5.6\my.ini" MySQL56
这里显示my.ini文件不是执行Program Files里添加的,而是ProgramData里的。则有两种方式让自己添加的数据生效。
一、修改ProgramData里的my.ini文件
二、修改服务里的可执行文件的路径,这个需要在运行里输入regedit,打开注册表,找到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MySQL56,修改ImagePath
2.数据表的编码设定:已存在的表
- 更改数据表编码格式:ALTER TABLE tbl_name CHARACTER SET utf8;
- 更改数据表里列的编码格式:ALTER TABLE tbl_name CHANGE 旧字段名 新字段名 字段类型 CHARACTER SET utf8 NOT NULL,更改前后字段类型要相似
- 解决多张表的字符编码问题:
- 导出表结构:mysqldump -u root - p --default-character-set=utf8 -d db_name > 存放路径/文件名.sql
- 导出数据表的数据:mysqldump -u root -p --quick --no-create-info --extended-insert --default-character-set=utf8 db_name > 存放路径/文件名.sql
- 删除原有的数据库
- 以新的编码格式创建数据库:
- 导入结构:mysql -u root -p test < C:/Develop/mysql/test.sql
- 导入数据,需要在数据中添加 set names 'utf8' ,mysql -u root -p test < C:/Develop/mysql/test_data.sql
备份命令:mysqldump -h [ip地址] -P [端口号] -u [用户名] -p [数据库] > [sql脚本文件]
还原命令:mysql -h [ip地址] -P [端口号] -u [用户名] -p [数据库] < [sql脚本文件]
注意:导入导出不要使用 powershell ,直接使用 cmd。
变量
1.会话变量
- 查看会话变量:
- SHOW SESSION VARIABLES; SHOW SESSION VARIABLES LIKE 'auto%';
- 查看指定的变量:SELECT @@SESSION.变量名
- 设置会话变量:SET @@SESSION.变量名=值 或者 SET 变量名=值
2.全局变量
- 查看全局变量:
- SHOW global VARIABLES; SHOW GLOBAL VARIABLES;
- SELECT @@global.变量名;
- 设置全局变量:SET global 变量名=值 或者 SET @@global.变量名=值
3.区别:会话变量只针对当前用户有效,全局变量是针对整个mysql数据库。
存储过程
常用的操作数据库语言SQL语句在执行的时候需要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定的存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它。
一个存储过程是一个可编程的函数,它在数据库中创建并保存。它可以有SQL语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中的面向对象方法的模拟。它允许控制数据的访问方式。
存储过程的优点:增强了SQL语言的功能和灵活性;存储过程允许标准组件是编程;存储过程能实现较快的执行速度。
1.创建存储过程:
- 选中一个数据库
- 改变分隔符,不要让分号
;
作为执行结束的标记,DELIMITER 新的分隔符
,比如DELIMITER ~
- 创建存储过程:
CREATE PROCEDURE p_name()
BEGIN
语句1;
语句2;
END~
-- 调用存储过程
CALL p_name~
2.参数和变量
- 局部变量:DECLARE 变量名 数据类型 DEFAULT 默认值;
- 三种参数
- IN :输入参数,表示该参数的值必须在调用存储过程之前指定,在存储过程中修改的值不能被返回
- OUT :输出参数,该值可在存储过程内部改变,并可以返回
- INOUT :输入输出参数,该值可以在调用时指定,并可修改和返回
CREATE PROCEDURE p_vartest1(IN p_var INT)
BEGIN
SELECT p_var;
SET p_var=p_var+1;
SELECT p_var;
END~
-- 创建一个名为@P的变量,没有@符号是不能创建成功的
SET @P=3~
-- 调用存储过程,并传递参数
CALL p_vartest1(@P)~
-- 查看调用存储过程后的@P值,是否有变化
SELECT @P;
3.流程控制
- 选择语句(IF ELSEIF ELSE CASE分支):ELSEIF是挨着写的,在SQL语句中除了IF、CASE,还有IFNULL
IF search_condition THEN statement_list
[ELSEIF search_condition THEN statement_list] ...
[ELSE statement_list]
END IF
CREATE PROCEDURE p_if(in age INT)
BEGIN
IF age>=18 && age<30 THEN
SELECT '成年人';
ELSEIF age>=30 && age<60 THEN
SELECT '中年人';
ELSE
SELECT '老年人';
END IF;
END~
-- case_value便是条件判断的变量,when_value表示变量的取值
CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE;
CREATE PROCEDURE p_case(in salaryId INT)
BEGIN
DECLARE addS INT;
CASE salaryId
WHEN 1001 THEN SET addS = 1500;
WHEN 1002 THEN SET addS = 2000;
WHEN 1003 THEN SET addS = 2500;
ELSE SET addS=1000;
END CASE;
UPDATE salaries SET salary=addS WHERE id=salaryId;
END~
- 循环语句
- while 语句: WHILE 条件 DO ... END WHILE;
- repeat 语句: REPEAT ... UNTIL 条件 END REPEAT;
- loop 语句: 循环名称:LOOP ... IF 条件 THEN LEAVE 循环名称; END IF; END LOOP;
CREATE PROCEDURE p_while()
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE result INT DEFAULT 0;
WHILE i<=100 DO
SET result=result+i;
SET i=i+1;
END WHILE;
SELECT result;
END~
CREATE PROCEDURE p_repeat()
BEGIN
DECLARE min_var INT DEFAULT 1;
DECLARE max_var INT DEFAULT 1;
SELECT MIN(id) INTO min_var FROM tbl_name;
SELECT MAX(id) INTO max_var FROM tbl_name;
REPEAT
IF min_var%2 = 0 THEN
UPDATE tbl_name SET gender='F' WHERE id=min_var;
END IF;
SET min_var = min_var + 1;
UNTIL min_var > max_var
END REPEAT;
END~
CREATE PROCEDURE p_loop()
BEGIN
DECLARE min_var INT DEFAULT 1;
DECLARE max_var INT DEFAULT 1;
SELECT MIN(id) INTO min_var FROM tbl_name;
SELECT MAX(id) INTO max_var FROM tbl_name;
loop_name:LOOP
IF min_var%2 = 0 THEN
UPDATE tbl_name SET gender='F' WHERE id=min_var;
END IF;
SET min_var = min_var + 1;
IF min_var > max_var THEN
LEAVE loop_name;
END IF;
END LOOP;
END~
4.定义条件和处理
条件的定义和处理可以用来定义过程中遇到问题时相应的处理步骤。
DECLARE CONTINUE HANDLER FOR sqlstate '错误代码值' SET 变量=变量值
CREATE PROCEDURE p_insert()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @X=1;
INSERT INTO test11(username) VALUES('aaa');
INSERT INTO test2(username,password) VALUES('abc','aab');
END~
ERROR 1146 (42S02):Table 'test11' doesn't exists
-- 错误代码 42S02 是表不存在,添加了CONTINUE就会直接跳过错误向下执行
5.存储过程管理
- 查看存储过程:SHOW PROCEDURE STATUS WHERE db='数据库名';
- 查看当前数据库下的存储过程的列表:SELECT specific_name FROM mysql.proc;
- 查看存储过程的内容:
- SELECT specific_name,body FROM mysql.proc [WHERE specific_name=存储过程名字]
- SHOW CREATE PROCEDURE 存储过程名字
- 删除存储过程:DROP PROCEDURE 存储过程名字
- 修改存储过程:ALTER {PROCEDURE | FUNCTION} sp_name [characteristic ...]
- {CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA} | SQL SECURITY {DEFINER | INVOKER} | COMMENT 'string'
- NO SQL表示子程序中不包含SQL语句;READS SQL DATA表示子程序中包含读数据的语句;MODIFIES SQL DATA表示子程序中包含写数据的语句。SQL SECURITY {DEFINER | INVOKER} 指明谁有权限来执行。DEFINER表示只有定义者自己才能够执行;INVOKER表示调用者可以执行。COMMENT 'string'是注释信息。
函数
默认函数功能时关闭的,SHOW VARIABLES LIKE '%fun%'
可以查看到函数功能是否关闭,如果显示OFF,可以设置为ONSET global log_bin_trust_function_creators=1
。
创建函数
-- 返回是 RETURNS 不是 RETURN,数据类型和返回的数据类型要一致
CREATE FUNCTION 函数名( 变量1, 变量2,... )
RETURNS 数据类型
BEGIN
...执行的程序代码
RETURN 数据;
END;
CREATE FUNCTION add_f(a INT,b INT)
RETURNS INT
BEGIN
RETURN a + b;
END~
SELECT add_f(3,4)~ --> 7
删除函数
DROP FUNCTION [IF EXISTS] 函数名
DROP FUNCTION IF EXISTS add_f~
视图
视图是由查询结果形成的一张虚拟表。
如果某个查询结果出现的非常频繁,也就是,要经常拿这个查询结果来做子查询,就可以使用视图。
视图的好处:简化查询语句;可以进行权限控制;大数据表分表的时候,比如某张表的数据由100万条,那么可以将这张表分成四个视图。
创建视图
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
该语句能创建新的视图,如果给定了OR REPLACE子句,该语句还能替换已有的视图。select_statement是一种SELECT语句,它给出了视图的定义。该语句可从基表或其他视图进行选择。
-- 把一张表分成4个视图,分成四部分查询
CREATE OR REPLACE VIEW view_employee1
AS
SELECT * FROM employees WHERE emp_id % 4 = 0;
CREATE OR REPLACE VIEW view_employee2
AS
SELECT * FROM employees WHERE emp_id % 4 = 1;
CREATE OR REPLACE VIEW view_employee3
AS
SELECT * FROM employees WHERE emp_id % 4 = 2;
CREATE OR REPLACE VIEW view_employee4
AS
SELECT * FROM employees WHERE emp_id % 4 = 3;
视图管理
视图存放在 information_schema数据库下的views表里。
1.视图的算法
- Merge:合并的执行方式,每当执行的时候,先将我们视图的SQL语句与外部查询视图的SQL语句,混合在一起,最终执行;
- Temptable:临时表模式,每当查询的时候,将视图所使用的SELECT语句生成一个结果的临时表,再在当前的临时表内进行查询。
对于Merge,会将引用视图的语句的文本与视图定义合并起来,使得视图定义的某一部分取代语句的对应部分。
对于Temptable,视图的结果将被置于临时表中,然后使用它执行语句。
对于UNDEFINED,MySql将选择所要使用的算法。如果可能,它倾向于MERGE而不是TEMPTABLE,这是因为MERGE通常更有效,而且如果使用了临时表,视图是不可更新。
2.查看视图的定义:SHOW table status [FROM 数据库名] [LIKE '匹配']
3.删除视图定义:只能删除视图的定义,不能删除数据,必须有DROP权限
- DROP VIEW [IF EXISTS] view_name [RESTRICT | CASCADE]
4.查看权限:mysql>SELECT Drop_priv FROM mysql.user WHERE USER='root';
5.删除视图
- DROP VIEW IF EXISTS worker_view1;
6.删除多个
- DROP VIEW IF EXISTS department_view1,department_view2;
7.视图更新:某些视图是可更新的。也就是说,可以在诸如UPDATE、DELETE 或 INSERT 等语句中使用它们,以更新基表的内容。对于可更新的视图,在视图中的行和基表汇总的行之间必须具有一对一的关系。还有一些特定的其他结构,这类结构会是的视图不可更新。更具体地讲,如果视图包含下面中的任何一种,那么它就是不可更新的:
- 聚合函数(SUM(),MIN(),COUNT()等)
- DISTINCT
- GROUP BY
- HAVING
- UNSIGNED 或UNION ALL
- 位于选择列表中的子查询
- JOIN
- FROM 子句中的不可更新视图
- WHERE 子句中的子查询,引用FROM子句中的表
- 仅引用文字值(在该情况下,没有要更新的基本表)
- ALGORITHM = TEMPTABLE(使用临时表总会使视图成为不可更新的)
8.with check option的理解和应用:通过视图进行的修改,必须也能通过该视图看到修改后的结果。更新视图的数据,那么必须先满足视图的条件,满足之后才能够更新到基表中。
触发器
触发器是一种特殊的存储过程,它在插入、删除或修改特定表中的数据时触发执行,它比数据库本身标准的功能有更精细和更复杂的数据控制能力。
触发器的特性:
- 监视地点:一般就是表名
- 监视时间:update、delete、insert
- 触发事件:after、before
- 触发事件:update、delete、insert
触发器不能直接被调用,是由数据库主动去执行。
创建触发器
CREATE TRIGGER 语法:
CREATE TRIGGER trigger_name trigger_time trigger_event
ON tbl_name FOR EACH ROW trigger_stmt
触发程序是与表有关的命名数据库对象,当表上出现特定事件时,将激活该对象。
触发程序与命名为tbl_name的表相关,tbl_name必须引用永久性表,不能将触发程序与TEMPORARY表或视图关联起来。
trigger_time是触发程序的动作时间。它可以是BEFORE或AFTER,以指明触发程序是在激活它的语句之前或之后触发。
trigger_event指明了激活触发程序的语句的类型。trigger_event可以是下述值之一:
- INSERT:将新行插入表时激活触发程序,例如,通过INSERT、LOAD DATA和REPLACE语句
- UPDATE:更改某一行时激活触发程序,例如,通过UPDATE语句
- DELETE:从表中删除某一行时激活触发程序,例如,通过DELETE和REPLACE语句
注意:trigger_cvent与以表操作方式激活触发程序的SQL语句并不很类似,这点很重要。例如,关于INSERT的BEFORE触发程序不仅能被INSERT语句激活,也能被LOAD DATA语句激活。可能会造成混淆的例子之一是INSERT INTO .. ON DUPLICATE UPDATE ...语法:DEFORE INSERT
触发程序对于每一行激活,后跟AFTER INSERT触发程序,或BEFORE UPDATE和AFTER UPDATE触发程序,具体情况取决于行上是否有重复键。
对于具有相同触发程序动作时间和时间的给定表,不能有两个触发程序。例如,对于某一表,不能有两个BEFORE UPDATE触发程序。但可以有1个BEFORE UPDATE触发程序。
trigger_stmt是当触发程序激活时执行的语句。如果打算执行多个语句,可以使用DEGIN ... END符合语句结构。这样,就能使用存储子程序中允许的相同语句。
特别说明:
- 对于INSERT而言,就插入的行用new来标识,行中的每一列的值用new.列名来表示
- 对于DELETE而言,原本有一行,后来被删除,想引用被删除的这一行,用old来表示,old.列名可以引用被删除的行的值
- 对于update而言,其修改的行,修改前的数据,用old来表示,old.列名引用被修改之前中的值;修改后的数据,用new来表示,new.列名引用被修改之后运行中的值。
CREATE TRIGGER tr_insert AFTER INSERT
ON employee FOR EACH ROW
BEGIN
INSERT salaries VALUES(new.emp_no,0,'2019-05-10');
END~
CREATE TRIGGER tr_delete AFTER DELETE
ON employee FOR EACH ROW
BEGIN
DELETE FROM salaries WHERE emp_no=old.emp.no;
END~
触发器的管理
1.查看所有触发器:SHOW TRIGGERS;
2.MYSQL中有一个information_schema.TRIGGERS表,存储所有库中的所有触发器,DESC information_schema.TRIGGERS,可以查看到触发器结构。
3.查看触发器名字:SELECT * FROM information_schema.TRIGGERS WHERE TRIGGER_NAME='触发器名字'\G
4.删除触发器:DROP TRIGGER [schema_name.]trigger_name
MyISAM表锁
锁是计算机协调对个进程或线程并发访问某一资源的机制。在数据库中,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。
MYSQL锁机制相比其他数据库,最显著的特点是不同的存储引擎支持不同锁机制。比如MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking);BDB存储引擎采用的是页面锁(page-level locking),但也支持表级锁;INNODB既支持行级锁(row-level locking),也支持表级锁,但默认是行级锁。
- 表级锁:开销小,加锁块,不会出现死锁;锁粒粒度大,发生锁冲突的概率高,并发度最低
- 行级锁:开销大,加锁慢,会出现死锁;并发度最高
- 页面锁:开销介于之间,会出现死锁,并发度一般。
从锁的角度说,表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如WEB应用;而行级锁更适合于有大量按索引条件并发更新少量不同数据,同时又并发查询的应用,比如一些在线事务处理(OLTP)系统。
共享读锁
先把数据库导出,在导出的.sql文件中添加set storage_engine = MyISAM;
,然后再导入,确保成为MyISAM存储引擎。
MySQL的表级锁有两种模式:表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)。
对于MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;对于写操作,则会阻塞其他用户对同一表的读和写操作;读操作和写操作之间,以及写操作之间是串行的。
一个SESSION使用LOCK TABLE命令给表加了读锁,这个SESSION可以查询锁定表中的记录,但更新或访问其他表会提示错误;同时,另外一个SESSION可以查询表中的记录,但更新就会出现锁等待。
1.加共享读锁:LOCK TABLE tbl_name READ;
2.解锁:UNLOCK TABLES;
独占写锁
1.加独占写锁:LOCK TABLE tbl_name WRITE;
2.解锁:UNLOCK TABLES;
并发插入
MyISAM表的读和写是串行的,但就总体而言,在一定条件下,MyISAM表也支持查询和插入操作的并发进行。
该引擎有一个系统变量consurrent_insert,专门用以控制其并发插入的行为,其值分别可以为0、1和2.
- 当为0时,不允许并发插入
- 当为1时,如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM运行在一个进程读表的同时,另一个进程从表尾插入记录。这也是MYSQL的默认设置
- 当为2时,无论MyISAM表中有没有空洞,都允许在表尾并发插入记录
锁调度:一个进程请求读锁,另一个进程请求同一表的写锁;写进程先获得锁。MYSQL任务写请求更重要。MyISAM不适合有大量更新操作和查询操作。
解决方法:执行set low_priority_updates=1
,使该连接发出的更新请求优先降低,其中insert、delete也可以通过此方法指定。
事务
1.查看数据库是否支持事务(INNODB支持):SHOW ENGINES;
2.查看MYSQL当前默认的存储引擎:SHOW VARIABLES LIKE '%storage_engine%'
3.查看某张表的存储引擎:SHOW CREATE TABLE tbl_name
4.修改表的存储结构:
- CREATE TABLE ... type=InnoDB;
- ALTER TABLE tbl_name type=InnoDB;
创建事务
事务是为了保证数据的一致性,开启事务之后需要提交之后数据才会生效。
START TRANSACTION; 开启事务
COMMIT; 提交
SET AUTOCOMMIT=1; 自动提交
事务的回滚
回到事务发生之前的数据状态,通过 ROLLBACK;
补充:
- commit and chain; 表示提交事务之后重新开启了新的事务。
- rollback and release; 表示事务回滚之后断开和客户端的连接。
还原点:
Set autocommit=0;
insert into userinfo values(6,’test1’,’128’);
savepoint s1;
insert into userinfo values(6,’test2’,’128’);
savepoint s2;
执行完三条插入语句,select * from userinfo可以看到三条。如果你想回滚到最初roolback就是最初什么都没有做的状态。如果你想回到savepoint s1的状态(也就是插入一条test1那里): rollback to savepoint s1; 。
事务更改被锁定: lock table 事务名称 writes;
解锁,让其他客户端可读: start transaction;
事务的4个属性:原子性、一致性、隔离性、持久性,这四个属性通常称为ACID特性。
- 原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做;
- 一致性(consistencr):事务必须是使数据库从一个一致性状态变到另一个一致性状态,一致性与原子性密切相关;
- 隔离性(isolation):一个事务的执行不能被其他事物干扰。即一个事物内部的操作及使用的数据对并发的他事物是隔离的,并发执行的各个事物之间不能互相干扰;
- 持久性(durability):持久性也称永久性,指一个事物一旦提交,它对数据库中的数据的改变应该是永久性的。接下来的其他操作或鼓掌不应该对其有任何影响。
慢查询
MYSQL 记录下查询超过指定时间的语句,我们将超过指定时间的SQL语句查询成为‘慢查询’。
查看慢查询设定时间:SHOW VARIABLES LIKE '%long%';
获取慢查询
SHOW status语句,获取当前数据库运行的时间:
- SHOW status LIKE 'uptime%'
- SHOW status LIKE 'com_Select'
- SHOW status LIKE 'connections'
- SHOW status LIKE 'slow_quries'
启动慢查询
启动慢查询需要以安全模式启动mysql服务,安全模式可以通过日志恢复数据库:mysql.exe --safe-mode --slow-query-log
数据库存储日志存放位置可以在my.ini中的datadir=‘...’查看到,然后打开到该文件夹,就能看到ZY-slow.log文件。超过设定时间,通常是5s-10s,就能在.log文件中看到。
配置慢查询
在mysql的配置文件中添加参数:
-- 文件和文件夹是已经创建好的
log-slow-queries=C:/MySQL/log/mysqld-slow-query.log
-- 慢查询的时间设置
long-query-time=5
-- 及时没有超过时间,但如果没有使用到索引,也会记录SQL语句
log-queries-not-using-indexes
索引
在关系数据库中,索引是一种与表有关的数据库结构,它可以使对于于表的SQL语句执行更快。
索引的分类
1.主键索引:ALTER TABLE tbl_name PRIMARY KEY(字段名)
2.唯一索引:唯一索引所在的列可以为NULL值;唯一索引所在的列不能为空字符串。注:列名即字段名
CREATE UNIQUE INDEX 索引名称 ON tbl_name(列名)
3.普通索引: CREATE INDEX 索引名称 ON tbi_name(字段名)
4.全文(FULL TEXT)索引: 用于全文搜索,只有MyISAM表类型支持FULL TEXT索引;FULL TEXT索引只可以从CHAR、VARCHAR和TEXT列中创建;整个列都会被编入索引,不支持部分列编索引。
-- 查看数据表articles中title,body字段中包含database单词的
SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('database');
-- 查看全文匹配度
SELECT id,MATCH(title,body) AGAINST ('Tutorial') FROM articles;
索引的管理
1.查看索引:SHOW KEYS FROM tbl_name 或者 SHOW INDEXS FROM tbl_name
2.删除索引:ALTER TABLE tbl_name DROP INDEX 索引名称
3.通过Explain分析具体有没有使用索引,执行低效SQL的执行计划:
EXPLAIN SELECT 索引名称(字段名) FROM tbl_name\G;
EXPLAIN SELECT 字段名 FROM tbl_name\G;
通过索引优化SQL
索引原理:主要通过二叉树去寻找索引文件,效率:log2N 检索10次:2的10次方,1024条记录
索引带来的开销:
- .frm 文件: 表示表的结构
- .myd 文件: 表示数据
- .myi 文件: 表示索引的文件
哪些不适合创建索引:更新非常频繁的字段;唯一性比较差的字段,比如人的性别。
创建索引的条件:肯定在WHERE条件中经常使用到的;该字段的变化不会太频繁。
通过 SHOW PROFILE 分析 SQL 具体消耗时间:
- 首先查看 mysql 是否支持 SHOW PROFILE
SELECT @@HAVE_PROFILING; - 如果 PROFILING 是关闭的,可以通过 SET 语句在 SESSION 级别开启 PROFILING
SET PROFILING=1; - 执行完毕之后,可以通过 SHOW PROFILES; 语句,查看当前 SQL 的 QUERY ID
- 执行 SELECT COUNT(*) FROM 表名;
- 通过 SHOW PROFILE FOR QUERY ID;。
优化
表的分析、检查、优化:
1.定期分析表:ANALYZE [ LOCAL | NO_WRITE_TO_BINLOG ] TABLE tbl_name [,tbl_name]
2.定期检查表:CHECK TABLE tbl_name [,tbl_name ] [option]
备注:CHECK TABLE 也可以检查视图是否有错误,比如在视图定义中被引用的表已不存在
3.定期优化表:OPTIMIZE [ LOCAL | NO_WRITE_TO_BINLOG ] TABLE tbl_name [,tbl_name]
对于MyISAM表,OPTIMIZE TABLE按如下方式操作:
- 如果表已经删除或分解了行,则修复表;
- 如果未对索引页进行分类,则进行分类
- 如果表的统计数据没有更新(并且通过对索引进行分类不能实现修复),则进行更新
注意:无论是ANALYZER,CHECK还是OPTIMIZE在执行期间将对表进行锁定,因此请注意这些操作要在数据库不繁忙的时候执行。
获取表的相关信息
SHOW TABLE STATUS 获取表的信息
SHOW TABLE STATUS LIKE 'tableName'\G
1.Name:表名称
2.Engine:表的存储引擎
3.Version:版本
4.Row_format:行格式
5.Rows:表中的行数
6.Avg_row_length:平均每行包括的字节数
7.Data_length:整个表的数据量(单位:字节)
8.Max_data_length:表可以容纳的最大数据量
9.Index_length:索引占用磁盘的空间大小
10.Data_free:未使用空间
11.Auto_increment:下一个自增长值
12.Create_time:表创建时间
13.Update_time:表最近更新时间
14.Check_time:使用check table或myisamchk工具检查表的最近时间
15.Collation:表的默认字符集和字符排序规则
16.Checksum:启用则对整个表的内容计算时的检验和
17.Create_options:指表创建时的其他所有选项
18.Comment:包含了其他额外信息
表的分区
当数据量过大的时候,需要将一张表的数据划分几张表存储。一些查询可以得到极大的优化,这主要是有助于满足一个给定WHERE语句的数据可以值保存在一个或多个分区内,这样在查找时就不用查找其他剩余的分区。
查看是否支持分区:SHOW VARIABLES LIKE '%partition%'; yes表示支持分区。
分区的分类:
- RANGE分区:基于属于一个特定连续区间的列值,把多行分配给分区
- LIST分区:类似与按RANGE分区,区别在于它是基于列值匹配一个离散值集合中的某个值来进行选择
- HASH分区:基于用户定义的表达式的返回值来进行选择的分区
- KEY分区::类似与HASH分区,区别在于它只支持计算一列或多列
CREATE TABLE employees(
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NU;; DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)
partition BY RANGE(store_id)(
partition p0 VALUES LESS THAN(6),
partition p1 VALUES LESS THAN(11),
partition p2 VALUES LESS THAN(16),
partition p3 VALUES LESS THAN MAXVALUE
);
-- 查看分区
SHOW CREATE TABLE employees\G
分区的删除:ALTER TABLE 表名 DROP PARTITION 分区名
增加分区:ALTER TABLE 表名 ADD PARTITION(PARTITION 分区名字 VALUES LESS THEN 具体的某个值)
内存优化
myisam内存优化:
1.key_buffer_size设置,决定索引块缓存区的大小,一般的myisam数据库,建议用1/4可用内存分配给key_buffer_size:
key_buffer_size=2G
2.read_buffer_size,经常顺序扫描myisam表,就需要设置,该值是每个session独占的,如果默认值设置太大,就会造成内存浪费。
3.read_rnd_buffer_size,需要做排序的myisam表查询,如带有order by子句的sql,适当增加该值。但需要注意,该值是每个session独占的,设置太大内存浪费。
innodb内存优化:
1.innodb_buffer_pool_size,决定表数据和索引数据的最大缓存区大小
2.innodb_log_buffer_size,决定innodb重做日志缓存的大小,对应有大量更新记录的事务,增加该值大小,可以避免在事务提交前就执行不必要的日志写入磁盘操作。
mysql并发参数:
1.max_connections,提高并发连接
2.thread_cache_size,加快连接数据库的速度,控制mysql缓存客户服务线程的数量
3.innodb_lock_wait_timeout,控制innodb事务等待行锁的时间
应用程序优化
1.访问数据库采用连接池优化,就是连接数据库的客户端放在一个连接池里。
2.采用缓存减少对mysql的访问:
- 避免对同一数据做重复检索,尽可能选择多个字段
- 使用查询缓存,比如一条SQL查询除了字段名和表明不一样,其他都一样,mysql就会把SQL语句1缓存,发给SQL2语句
- 缓存参数的配置
- query_cache_type:是否打开缓存,大小写要一样,以下是可选项
- OFF :关闭
- ON:总是打开
- DEMAND:只有明确写了SQL_CACHE的查询才会吸入缓存
- query_cache_size:缓存使用的总内存大小空间,单位字节,必须是1024的整数倍,否则MYSQL实际分配可能跟这个数值不同
- query_cache_min_res_unit:分配内存块时的最小单位大小
- query_cache_limit:MYSQL能够缓存的最大结构,如果超出则增加query_not_cached的值,并删除查询结果
- query_cache_wlock_invalidate:如果某个数据表被锁住,是否仍然从缓存中返回数据,默认是OFF,便是仍然返回
- query_cache_type:是否打开缓存,大小写要一样,以下是可选项
3.负载均衡(读写分离):一个主MYSQL服务器(MASTER)服务器与多个从属MYSQL服务器(STAVE)建立复制(replication)连接,主服务器与从属服务器实现一定程度上的数据同步,多个从属服务器存储相同的数据副本,实现数据冗余,提供容错功能。部署开发应用系统时,对数据库操作代码进行优化,将写操作(如UPDATE、INSERT)定向到主服务器,把大量的查询操作(SELECT)定向到从属服务器,实现集群的负载均衡功能。
如果主服务器发生故障,从属服务器将转换角色成为主服务器,是应用系统为终端用户提供不剪短的网络服务;主服务器恢复运行后,将其转换为从属服务器,存储数据库副本,继续对终端用户提供数据查询检索服务。
账号管理
查看用户:
mysql>USE mysql;
mysql>SELECT host,user,password FROM user;
1.GRANT命令使用
对于ZY用户,赋予SELECT的权限,能查看所有数据库和所有数据表
GRANT SELECT ON . TO ZY@'localhost' IDENTIFIED BY 'PWD' WITH GRANT OPTION;;
对应YZ用户,赋予test下索引数据表的索引权限
GRANT ALL PRIVILEGES ON test.* TO YZ@'localhost' IDENTIFIED BY 'PWD' WITH GRANT OPTION;;
- ALL PRIVILEGES :表示多有权限,你也可以使用SELECT、UPDATE等提到的权限
- ON :用来指定权限针对哪些库和表
- test.* :test数据库下的所有表
- TO :表示将权限赋予给哪个用户
- YZ@'localhost' :表示test用户,@后面接限制的主机,可以是IP、IP段、域名以及%,%表示任何地方,但有的版本不包括本地,如果不包括需要再加一个localhost的用户
- IDENTIFIED BY :指定用户的登录密码
- WITH GRANT OPTION :表示该用户可以将自己拥有的权限
2.查看用户的权限:
SHOW GRANTS FOR ‘root’@'localhost'
3.删除用户,不仅仅要删除用户的名称,还要删除用户拥有权限。
使用DELETE删除,并不能删除权限,新建同名用户后会继承以前的权限,正确的做法是使用DROP命令:
DROP USER ‘zy’@'localhost' ;
4.修改密码
SET PASSWORD FOR 'ty'@'localhost'=password('123');
5.对账号权限的资源设置
GRANT SELECT ON employees.* TO test@localhost IDENTIFIED BY 'pwd' WITH max_queries_per_hour 5 max_user_connections 6;
- 设置test用户对employees数据库的权限,每小时查询的次数小于5次,最多有6个用户进行并发连接
MYSQL监控
随着软件后期的不断升级,mysql的服务器数量越来越多,软硬件故障的发生概率也越来越高。这个时候需要一套监控系统,当主机发生异常时,此时通过监控系统发现和处理。
1.常见监控方式的分类:下面语句没有分号;
- 自己写程序或者脚本控制
- 监控mysql是否提供正常的服务:mysqladmin -uroot -proot -hlocalhost ping,输出:mysql is alive
- 获取当前的几个状态值:mysqladmin -uroot -proot -hlocalhost status
- 获取数据库当前的连接信息:mysqladmin -uroot -proot -hlocalhost processlist
- 获取当前数据库的连接数:mysql -uroot -proot -BNe "select host,count(host) from processlist group by host;" information_schema
- 检查修复分析优化:mysqlcheck -u root -proot --all-databases
- 在客户端执行以下命令
- 检查临时表是否过多:SHOW STATUS LIKE 'Created_tmp%'
- 锁定状态:SHOW STATUS LIKE "%lock%"
- Inonodb_log_waits反应Innodb Log Buffer空间不足造成等待的次数:SHOW STATUS LIKE 'Innodb_log_waits'
- 监控采用商业解决方案
- 监控开源软件
定时维护
mysql 设置定时器,从5.1开始才支持event的。查看版本SELECT VERSION();
1.查看是否开启event与开启event
- 查看evevt的状态:SHOW VARIABLES LIKE '%sche%'
- 开启evevt功能:SET GLOBAL event_scheduler=1;
2.创建定时器,创建事件test_event:
DROP EVENT IF EXISTS test_event;
CREATE EVENT test_event
ON schedule every 1 second
ON completion preserve disable
DO CALL p_test_proce();
-- 当为on completion preserve的时候,当event到期了,event会被disable,但该event还会存在
-- 当为on completion not preserve的时候,当event到期时,该event会被自动删除
-- p_test_proce是一个存储过程的名字
- 开启事件test_event:ALTER EVENT test_event ON completion preserve enable;
- 关闭事件test-event:ALTER EVENT test_event ON completion preserve disable;
备份与还原
1.备份:
- 通过mysqldump命令备份:
- 备份单个数据库:mysqldump -u username -p dbname [table1 table2] > backupName.sql
- dbname 表示数据库的名称,table1 table2表示备份表名称,backupName.sql参数表设计备份文件的名称
- 备份多个数据库:mysqldump -u username -p --databases dbname1 dbname2 >backup.sql
- 备份所有数据库:mysqldump -u username -p -all-databases > bakcupName.sql
- 备份单个数据库:mysqldump -u username -p dbname [table1 table2] > backupName.sql
- 直接复制整个数据库目录
- 使用mysqlhotcopy工具快速备份
2.还原
- 使用mysql命令还原mysqldump备份的数据库:
- mysql -u root -p [dbname] < backupName.sql