约束
查看约束
show keys from 表名; 看不了非空约束
或者
show index from 表名;看不了非空约束
删除约束
show keys from 表名;
drop index id on 表名
唯一性约束
语法
列级定义
create table 表名 (id int unique,name char(10));
表级定义
create table 表名 (id int,name char(10),unique(id));
追加定义
create table 表名(id int,name char(10));
alter table 表名 modify id int unique;
主键约束
列级定义
create table 表名 (id int primary key,name char(10));
表级定义
create table 表名 (id int,name char(10),primary key(id));
修改表时追加约束(事后)
建表之后根据需要追加
追加定义
alter table 表名 add primary key(id);
非空约束
非空约束用于确保其所在列的值不能为空值null
只有列级定义和追加定义
语法
列级定义
create table 表名 (id int not null,name char(10));
追加定义
alter table 表名 modify name char(10) not null;
外键约束
语法
表级定义
create table 表名(id int,name char(10),pid int,primary key(id),foreign key(pid) references 表名(id));
追加定义
create table 表名(id int,name char(10),pid int);
alter table 表名 add primary key(id);
alter table 表名 add foreign key(pid) references 表名(id);
索引
- 创建添加
建表时创建索引
create table 表名(id int,name varchar(20),index idx_name (name));
给表追加索引
alter table 表名 add unique index idx_id(id);
给表的多列上追加索引,以下2种方式均可
alter table 表名 add index idx_id_name(id,name);
create index idx_id_name on 表名(id,name);
- 查看
查看表列上的索引索引,以下2种方式均可
show index from 表名;
show keys from 表名; --mysql中索引也被称为keys
- 删除
使用alter table命令删除索引
alter table 表名 drop index 索引名
使用drop index命令删除索引:
drop index 索引名 on 表名
- 利弊
大表(记录数多),仅从中找出少量行(总行数的3%-%5)
在经常作为查询条件(where)的列上添加索引,返回记录少,就可能用上索引,起到加速查询的作用
索引和表的区别是索引页之间存在关联关系,但是会占用额外的磁盘空间,有可能出现索引占的磁盘空间比表还大的情况
用户管理
- 用户从职权上可分为超级用户和普通用户
root用户不同于操作系统的root用户,默认对所有数据库和表具有完全访问权限
普通用户在创建数据库时具有连接数据库的权限,仅对information_schema数据库中的表的部分行具有读取权限(select)
对于实际的生产库,应尽量避免应用程序使用root用户直接操纵数据库
应根据业务需求建立普通用户并授权使其能够完成权限内的任务,防止未经授权用户访问超出其特权的数据
- 查看用户
select user,host,authentication_string from mysql.user; - 创建用户
例如
create user zhang@localhost identified by ‘zhang’;
create user ma identified by ‘ma’;
create user ‘tom’@’192.168.2.1’identified by ‘tom’; - 修改自己密码
set password=password(‘newpass’);
修改其他用户密码(要有相应权限)
mysql> set password for ‘username’@‘host’= password(‘newpass’);
使用rename user命令可以给用户名和客户端主机改名
使用drop user语句可以删除用户
grant语句可以用来创建用户也可以修改用户的权限
使用show grants语句查看用户拥有的权限
revoke语句可以用来撤销用户所拥有的权限 - MySQL权限级别
全局 *.*
数据库级 <dbname>.*
表级 <dbname>.<tabname>
列级
存储过程 <dbname>.<procname>
MySQL 日志文件
错误日志 (error log)
记录mysqld启动、运行和停止过程中遇到的问题
默认开启
日志位置
mysql> show variables like ‘log_error’;
常规日志 (general query log)
记录客户端连接以及服务器从客户端收到的各类SQL语句
默认关闭
日志位置
mysql> show variables like ‘general_log%’;
默认名称:hostname.log
开启常规日志
mysql> set global general_log=on;
慢查询日志 (slow query log)
记录运行时间超过选项long_query_time设定阈值的查询语句
默认关闭
日志位置
mysql> show variables like ‘slow_query_log%’;
mysql> show variables like ‘long_query_time%’;
默认名称:hostname-slow.log
long_query_time默认时长10秒,执行超过10秒的查询语句会记录到慢查询日志中
二进制日志 (binary log)
记录使数据库数据产生变化的各类语句
内容:
BINLOG记录数据库的变更过程。例如创建数据库、建表、修改表等DDL操作、以及数据表的相关DML操作,这些操作会导致数据库产生变化,开启binlog以后导致数据库产生变化的操作会按照时间顺序以“事件”的形式记录到binlog二进制文件中
默认关闭
用途
binlog有两个重要用途:
数据库复制
数据恢复
查看BINLOG是否开启
mysql> show variables like ‘%log_bin%’;
如果log_bin的值为OFF说明没有开启binlog
开启BINLOG
root# vi /etc/my.cnf
在[mysqld]下面添加下面行内容
server-id=1
log-bin=mysql-bin
root# systemctl restart mysqld
mysql> show variables like ‘%log_bin%’;
这3种情况会导致BINLOG日志切换:
1: MySQL启动或重启
2: 日志量到达了max_binlog_size的设定值
3: 执行flush logs;命令手动切换日志
mysql> flush logs;
查看binlog中部分内容,自定义起始和结束头标注
mysqlbinlog --start-position=219 --stop-position=546 /var/lib/mysql/mysql-bin.000005
备份与恢复
备份分类1 – 按照备份数据文件的格式
物理备份
生成数据库文件的完整副本(二进制),可以使用标准命令,如 cp、tar、xcopy、windows图形复制粘贴
备份可以在不同的计算机体系结构间还原。例如:linux的mysql还原给windows的mysql
比逻辑备份和还原的速度快
数据库文件在物理备份期间不能有更改,因为要保证数据的一致性
对于默认引擎为innodb的数据库需要停止MySQL服务后再进行物理备份(冷备)
逻辑备份
基于数据库复制的备份
逻辑备份
将数据库和表转换为一个文本文件,里面包括可以重构数据库和表的SQL语句
可以使用该文本文件在运行不同体系结构的其他主机上重新装入数据库
要求 MySQL 服务器在备份期间运行 (不能冷备)
可以备份本地和远程 MySQL 数据库服务器
通常比物理备份(二进制)的速度慢
逻辑备份文件的大小可能会超过所备份的数据库物理文件大小
基于数据库复制的备份
创建一个主库的复制库从库,主库作为生产库,从库作为备份库
主库定期向从库传递binlog文件,并在从库应用保证从库和主库的一致性
从库也可以做物理备份或逻辑备份
缺点:
成本较高,因为必须有另一台服务器和存储设备用于从库
从库相对于主库会有延迟
备份分类2 – 按照备份的完整度
完全备份
完全备份
备份所有数据库文件:/var/lib/mysql/*
备份所有binlog文件: /var/lib/mysql/mysql-bin.*
备份选项文件: /etc/my.cnf
不完全备份
仅仅备份部分数据库的文件
不完全备份
备份分类3 – 按照MySQL服务器的状态
热备
数据库不关闭,在仍然有用户读取或修改数据的过程中进行备份
热备不阻止用户正常的数据库操作,有些热备工具甚至能捕获备份进行期间发生的更改
并不是所有引擎都支持热备,innodb引擎可以支持热备,但MyISAM引擎不能热备,可以温备和冷备
温备
数据库不关闭,处于只读模式,备份可以在用户读取数据时进行
温备优点是不必完全锁定数据库访问用户,其不足之处在于用户无法在进行备份时修改数据库的数据
冷备
关闭数据库,备份在用户不能访问数据时进行,因此用户无法读取或修改数据
冷备会阻止执行任何使用数据的活动,如果备份时间较长,会造成用户较长的时间里无法访问数据
总结
- 简单查询
执行步骤:
select c1,c2,… from tab_name where xxx=xxx group by xxx having xxx=xxx order by xxx limit
3 1 2 4 5 6 7
复杂查询
多表连接
交叉连接(笛卡尔积)
select * from a cross join b;
记录数 = a表记录 * b表记录
等值连接
内连接
select * from a inner join b on a.id=b.id;
左连接 (左外连接)
select * from a left join b on a.id=b.id;
有连接 (右外连接)
select * from a right join b on a.id=b.id;
全连接 (全外连接) full join
select * from a full join b on a.id=b.id; (mysql不支持)
select * from a left join b on a.id=b.id union select * from a right join b on a.id=b.id;
非等值连接
例子:查看没有同学的bmi(体重指数=体重/身高^2)
select s.*,s.weight/(height/100*height/100) bmi,b.* from stu s join bmi b on s.weight/(height/100*height/100) BETWEEN b.lval and b.hval and s.sex=b.sex
子查询
非关联子查询
特点:子查询不依赖于主查询,可以单独执行;子查询只执行1次
例子:所有班中最高的那个同学是谁?
select * from stu where height=(select max(height) from stu);
例子:比许褚考分高的同学都是谁?
select * from stu where score>(select score from stu where sname='许褚');
关联子查询
特点:子查询依赖于主查询,不可以单独执行;主查询有几行记录,子查询就执行几次
例子:高于本班平均分的同学都是谁?
select o.*,(select avg(score) from stu i where i.cno=o.cno) avgscore from stu o where o.score>(select avg(score) from stu i where i.cno=o.cno);
内联试图 in-line view
特点:作为表的子查询,属于非关联子查询,mysql需要给子查询起个别名
例子:每个班最高的同学都是谁?
select * from stu s join (select cno,max(height) maxheight from stu group by cno) x on s.cno=x.cno and s.height=maxheight
例子:高于本班平均分的同学都是谁?
select * from stu s join (select cno,avg(score) avgscore from stu group by cno) x on s.cno=x.cno and s.score>avgscore
例子:求班级表中每个老师所带学生的数量?
select teacher,count(ifnull(sno,null)) cnt from (select c.*,s.sno,s.sname from class c left join stu s on c.cno=s.cno) x group by teacher order by 2 desc;
复合查询
union 去除重复行,自动排序
union all 不去除重复行,不排序
查询结果集上下叠加
select user,host,null from mysql.user union select cno,teacher,cname from class ;
例:同学的名字都有哪些中国字,统计字的个数
select zi,count(*) from (select * from (select substr(sname,1,1) zi from stu union all select substr(sname,2,1) from stu union all select substr(sname,3,1) from stu) x where zi!='') x group by zi
建表T
create database if not exists xyz;
use xyz;
create table t(id int,name char(10));
show tables;修改表名:
alter table t rename to t1;
show tables;添加字段:
add
t1表添加字段sal,decimal(8,2)
alter table t1 add sal decimal(8,2);
desc t1;修改字段类型:
modify
t1表修改name char(10) 到 varchar(10)
alter table t1 modify name varchar(10);
desc t1;修改字段名称:
change
t1表字段sal修改为salary
desc t1;
alter table t1 change sal salary decimal(8,2);
desc t1;修改字段位置:
desc t1;
修改字段salary成第一列
alter table t1 modify salary decimal(8,2) first;
修改字段salary成最后一列
alter table t1 modify salary decimal(8,2) after name;
desc t1;修改字段默认值:
desc t1;
修改salary默认值为1000.00
alter table t1 modify salary decimal(8,2) default 1000.00;修改字段为非空:
desc t1;
修改salary为非空
alter table t1 modify salary decimal(8,2) not null;
desc t1;追加表的某个字段唯一约束:
desc t1;
给字段name添加唯一性约束(name不能有重值,但是可以有空值)
alter table t1 add unique(name);
desc t1;追加表的某个字段为主键:
desc t1;
给字段id添加主键约束(id不能有重值,不能有空值)
alter table t1 add primary key(id);
desc t1;取消表的主键:
alter table t1 drop primary key;添加多列:
desc t1;
alter table t1 add col1 int,add col2 char(10),add col3 varchar(20);
desc t1;删除多列:
alter table t1 drop col1,drop col2,drop col3;
desc t1;
创建学生表:
use xyz;
create table student (sno int,sname varchar(20),age int,phone char(11));给学生表插入数据:
insert into student(sno,sname,age,phone) values(‘1’,‘zhangsan’,22,‘13011228822’);
insert into student(sno,sname,age,phone) values(‘2’,‘lisi’,23,‘13522885566’);
insert into student(sno,sname,age,phone) values(‘3’,‘wangwu’,25,‘13766337890’);
查看学生表结构:
desc student;查看学生表(所有列,所有行):
select * from student;查看学生表(sno列和sname列,所有行):
select sno,sname from student;查看学生表(sno列和sname列,sno为1的行):
select sno,sname from student where sno=1;查看学生表(所有列,电话135开头的行):
select * from student where phone like ‘135%’;查看学生表(所有列,电话135开头的行而且年龄大于20岁的行):
select * from student where phone like ‘135%’ and age>20;删除学生表(sno为3的学生)
delete from student where sno=3;
select * from student;修改学生表(sno为2的学生,age改成28,phone改成13501160001)
update student set age=28,phone=‘13501160001’ where sno=2;
select * from student;