一、用户管理:
创建用户:
create user '用户名'@'IP地址' identified by '密码';
删除用户:
drop user '用户名'@'IP地址';
修改用户:
rename user '用户名'@'IP地址'; to '新用户名'@'IP地址';
修改密码:
set password for '用户名'@'IP地址' = Password('新密码')
二、库相关操作
查看所有数据库:
1 SHOW DATABASES;
创建数据库 :
CREATE DATABASE cnblog(数据库名称,下同) CHARSET=UTF8;
删除数据库 :
DROP DATABASE cnblog;
切换数据库 :
USE cnblog;
查看当前数据库 :
SELECT DATABASE();
图例:
三、表相关操作
查看数据库中的所有表:SHOW TABLES;
创建表:
格式(中括号中可以不填):CREATE TABLE 表名(列名 数据类型 是否可以为空)[ ENGINE= INNODB DEFAULT CHARSET=UTF8 ]
1.数字
int[unsigned] 可以保存2的32次方大小的数,若有正负号,表示正负2的31次方
bigint可以表示很大的数
2.字符串
char(10)定长 若数据没有10长度会用空格补缺
varchar(10)变长 数据是多少就是多少
两者都只能表示255字节长度的字符串,
3.时间
一般用DATATIME 显示XXXX-MM-DD H-i-s
4.枚举
enum 插入数据时只能从Enum选项中选取
CREATE TABLE shirts (
name VARCHAR(40),
size ENUM('x-small', 'small', 'medium', 'large', 'x-large')
);
INSERT INTO shirts (name, size) VALUES ('dress shirt','large'), ('t-shirt','medium'),('polo shirt','small')
set 插入值只能是set选项中的组合
CREATE TABLE myset (col SET('a', 'b', 'c', 'd'));
INSERT INTO myset (col) VALUES ('a,d'), ('d,a'), ('a,d,a'), ('a,d,d'), ('d,a,d');
5.文件
如果文件过长,或者是图片,存取的是文件的url位置
基本数据类型
NOT NULL -不能为空
NULL -可为空
是否可为空
CREATE TABLE 表名(
num INT NOT NULL DEFAULT 6,
) ;
# 插入的这个数默认为6
默认值
1. 自增列为主键的情况
CREATE TABLE 表名(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
)
2. 自增列为索引
CREATE TABLE 表名(
id INT NOT NULL AUTO_INCREMENT,
index(id)
)
自增
1.主键可以为单个字段
CREATE TABLE 表名(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
)
2.主键可以为组合
CREATE TABLE 表名(
firstname VARCHAR(20) NOT NULL,
lastname VARCHAR(20) NOT NULL,
PRIMARY KEY (firstname,lastname)
)
主键
creat table color(
nid int not null primary key,
name char(16) not null
)
create table fruit(
nid int not null primary key,
smt char(32) null ,
color_id int not null,
constraint fk_cc foreign key (color_id) references color(nid)
)
外键
SHOW CREATE TABLE 表名
查看建表语句
DESC 表名
查看建表字段
修改表:
添加列:ALTER TABLE 表名 ADD 列名 类型
删除列:ALTER TABLE 表名 DROP COLUMN 列名
修改列:ALTER TABLE 表名 MODIFY COLUMN 列名 类型; -- 类型
修改外键:ALTER TABLE 从表 ADD CONSTRAINT 外键名称(形如:FK_从表_主表)FOREIGN KEY 从表(外键字段) REFERENCES 主表(主键字段);
删除外键:ALTER TABLE 表名 DROP FOREIGN KEY 外键名称
INSERT INTO 表名(列名,列名) VALUES (值,值);
eg: INSERT INTO student(name,tel) VALUES(‘小明’,‘13111311313’);
增
DELETE FROM 表名 WHERE 条件;
eg:DELETE FROM STUDENT WHERE sid=‘1001’ AND class=‘二班’
删
UPDATE 表名 SET 列=值 WHERE 条件
eg:UPDATE student SET points = 80 WHERE class=‘三班’
改
SELECT * FROM 表名
eg:SELECT * FROM STUDENT WHERE id>1
SELECT id,gender FROM student WHERE points>80
查
ALTER TABLE 表名 AUTO_INCREMENT=10
表示主键的值从10开始递增
修改主键的值
添加一个条件语句(语法case when ...then.... else .... end)
select max(num),min(num) case when min(num)<60 then 不及格 else min(num) end from score
最低分低于60分的会显示不及格,如果高于60分会显示最低是多少。
按条件查询(关键词where):
SELECT * FROM students WHERE age>10;
SELECT * FROM students WHERE id in (1,3,5);
SELECT * FROM students WHERE id BETWEEN 5 AND 16;(这是个闭区间)
SELECT * FROM students WHERE age=30 AND firstname=‘张';
SELECT * FROM students WHERE id in (SELECT id FROM male_students)(先从第二张表取id,再用此id查第一张表数据)
通配符查询(关键词like):
SELECT * FROM students WHERE name like '%平’;(查找名字以平结尾的)
SELECT * FROM students WHERE name like '_平’;(查找名字以平结尾的,只能为两个字)
SELECT * FROM students WHERE name like '%平%’;(查找名字中含有平的)
分页查找(关键字limit):
SELECT * FROM students limit 10; 取10条数据查看
SELECT * FROM students limit 20,10 从第20条开始向后取10条
SELECT * FROM students limit 5 offset 7 从第7条开始向后取5条
排序 (关键词 ORDER BY)
SELECT * FROM students ORDER BY id DESC;降序排列
SELECT * FROM students ORDER BY id ASC;升序排列
分组(关键字group by 和 having):
SELECT count(id) as mount, class_id FROM students GROUP BY cl
ass_id HAVING count(id) > 20;(注意:where语句不能接聚合函数的,如果要对分组后的结果进行二次筛选要用having)
连表操作(关键词LEFT JOIN ...ON):
SELECT student.name FROM student LEFT JOIN class ON student.cid = class.id
多张表相连:
SELECT student.name,teacher.id FROM student
LEFT JOIN class ON student.cid = class.id
LEFT JOIN teacher on class.teacher = teacher.id
LEFT JOIN 与 RIGHT JOIN区别:会以LEFT或RIGHT关联的表作为主显示表,从表没有数据会显示NULL
INNER JOIN 则会隐藏NULL的字段
注意:多张表关联时要引用字段,字段所在的表必须是关联好的不能凭空引入一个字段
索引:帮助我们快速的找到数据
索引文件存储的某种格式:
1.hash, 单值取值快, 但取多项数据时速度较慢
2.btree,单值没有hash速度快,但单次取数据查询次数少,对于多项数据速度较快
常见索引:
普通索引:加速查找
唯一索引:加速查找 + 不能重复
主键索引:加速查找 + 不能为空 + 不能重复
联合索引:
- 联合主键索引
- 联合唯一索引
- 联合普通索引
普通索引:
生成表时即创建普通索引
CREATE TABLE index_1(
nid int not null auto_increment primary key,
name char(32) not null,
email char(32) not null,
extra text,
index ix_name(name)
)
SQL语句创建索引
CREATE INDEX 索引名 on 表名(字段)
删除索引
DROP 索引名 on 表名;
查看索引
show index from 表名;
索引的缺点:
1.需要保存额外的索引文件
2.更新修改新建速度慢
3.要命中索引
- SELECT * FROM student WHERE name='一休', 命中
- SELECT * FROM student WHERE name LIKE '一休', 未命中
唯一索引:
创建表生成唯一索引
CREATE TABLE index_2(
nid int not null auto_increment primary key,
name varchar(32) not null,
email varchar(64) not null,
extra text,
unique ix_name (name) -- 将name字段设置为唯一索引
)
创建唯一索引
CREATE unique INDEX 索引名 on 表名(字段);
删除唯一索引
DROP unique INDEX 索引名 on 表名
主键索引
create table index_3(
nid int not null auto_increment primary key,
name varchar(32) not null,
email varchar(64) not null,
extra text,
index ix_name (name)
)
OR
create table index_4(
nid int not null auto_increment,
name varchar(32) not null,
email varchar(64) not null,
extra text,
primary key(ni1),
index ix_name (name)
)
创建主键
ALTER TABLE 表名 add PRIMARY KEY(列名)
删除主键
alter table 表名 drop primary key;
alter table 表名 modify 列名 int, drop primary key;
联合索引:
创建联合索引
create table index_5(
nid int not null auto_increment primary key,
name varchar(32) not null,
email varchar(64) not null,
extra text
)
create index ix_name_email on in3(name,email);
删除联合索引
- drop unique index 索引名称 on 表名
常见索引
在索引文件中直接获得数据
SELECT name FROM tb WHERE name='zhang'
覆盖索引
把多个单列索引合并使用
SELECT * FROM tb WHERE name=‘xxx’ AND id=3;
索引合并
在组合索引中,遵循最左前缀原则,比如索引为(name,class,tel)
查询条件为name时走索引,(name,class),(name,tel)都会走索引
但是如果是class或tel开头不走索引
1.like
select * from tb1 where name like '%cn';
2.使用函数
SELECT * FROM tb WHERE reverse(name) = 'zhang'
3.or
SELECT * FROM tb WHERE nid=1 or email='nn@qq.com'
注意:当or条件未建立索引才会失效或者后面接and条件是索引,也会忽略or
4.类型不一致
SELECT * FROM tb WHERE sid='999';(int类型却用字符串查找)
5.!=
SELECT * FROM tb WHERE sid != 99;
注意:如果条件是主键依然走索引
6.>
SELECT * FROM tb WHERE sid>99;
注意:如果条件是主键或整数类型会走索引
7.order by
SELECT name FROM tb order by sid;
注意:如果sid是索引 name非索引 则不走索引
如果order by接主键依然走索引
8.最左前缀匹配
不能命中索引的几种情况
1.避免使用SELECT *
2.创建表时尽量用char代替varchar
3.建表时固定长度的字段往前排
4.索引散列(重复少)不适合建索引(性别)
5.尽量使用短索引(text字段类型格式:text(18)以前18个字符建索引)
6.连表操作是条件类型需一直
索引应注意事项
作用:不执行sql语句,MySQL预估SQL语句执行时间
id
查询顺序标识
如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B;
+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 9 | NULL |
| 2 | DERIVED | tb1 | range | PRIMARY | PRIMARY | 8 | NULL | 9 | Using where |
+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
特别的:如果使用union连接气值可能为null
select_type
查询类型
SIMPLE 简单查询
PRIMARY 最外层查询
SUBQUERY 映射为子查询
DERIVED 子查询
UNION 联合
UNION RESULT 使用联合的结果
...
table
正在访问的表名
type
查询时的访问方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
ALL 全表扫描,对于数据表从头到尾找一遍
select * from tb1;
特别的:如果有limit限制,则找到之后就不在继续向下扫描
select * from tb1 where email = 'seven@live.com'
select * from tb1 where email = 'seven@live.com' limit 1;
虽然上述两个语句都会进行全表扫描,第二句使用了limit,则找到一个后就不再继续扫描。
INDEX 全索引扫描,对索引从头到尾找一遍
select nid from tb1;
RANGE 对索引列进行范围查找
select * from tb1 where name < 'alex';
PS:
between and
in
> >= < <= 操作
注意:!= 和 > 符号
INDEX_MERGE 合并索引,使用多个单列索引搜索
select * from tb1 where name = 'alex' or nid in (11,22,33);
REF 根据索引查找一个或多个值
select * from tb1 where name = 'seven';
EQ_REF 连接时使用primary key 或 unique类型
select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid;
CONST 常量
表最多有一个匹配行,因为仅有一行,在这行的列值可被优化器剩余部分认为是常数,const表很快,因为它们只读取一次。
select nid from tb1 where nid = 2 ;
SYSTEM 系统
表仅有一行(=系统表)。这是const联接类型的一个特例。
select * from (select nid from tb1 where nid = 1) as A;
possible_keys
可能使用的索引
key
真实使用的
key_len
MySQL中使用索引字节长度
rows
mysql估计为了找到所需的行而要读取的行数 ------ 只是预估值
extra
该列包含MySQL解决查询的详细信息
“Using index”
此值表示mysql将使用覆盖索引,以避免访问表。不要把覆盖索引和index访问类型弄混了。
“Using where”
这意味着mysql服务器将在存储引擎检索行后再进行过滤,许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where子句的查询都会显示“Using where”。有时“Using where”的出现就是一个暗示:查询可受益于不同的索引。
“Using temporary”
这意味着mysql在对查询结果排序时会使用一个临时表。
“Using filesort”
这意味着mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。mysql有两种文件排序算法,这两种排序方式都可以在内存或者磁盘上完成,explain不会告诉你mysql将使用哪一种文件排序,也不会告诉你排序会在内存里还是磁盘上完成。
“Range checked for each record(index map: N)”
这个意味着没有好用的索引,新的索引将在联接的每一行上重新估算,N是显示在possible_keys列中索引的位图,并且是冗余的。
执行计划
分页:
最常见的分页基于 SELECT * FROM text_tb limit 0,10
这样的分页当数据量很大时(例如千万级别的数据量),很耗费时间,解决方法有以下几点:
1. 只给浏览用户展示固定页数,比如200页,300页,减轻mysql检索压力
2. 用索引表(覆盖索引)
SELECT * FROM text_tb WHERE id in(SELECT id FROM text_tb LIMIT 1000000,10)
3.记录当前页最小id(比如150000)和最大id(150010)
下一页: SELECT * FROM text_tb WHERE id > max_id LIMIT 10;
上一页:SELECT * FROM text_tb WHERE id < min_id ORDER BY id DESC LIMIT 10;
4.给URL上的页数信息加密,无法直接访问到较大页数
注意:
1.id 不一定是连续的,所以不能用id bewteen xx and xx 来进行检索
2.中间页数的思路,根据前页的id 计算要跳到的页数的id,取到为止,倒序排列,并取头10个作为limit
select * from userinfo where id in (
select id from (select id from userinfo where id > max_id limit 30) as N order by N.id desc limit 10
)
分页相关