MySQL - 总结

MySQL总结

SQL语言主要用于存取数据、查询数据、更新数据和管理关系数据库系统,SQL语言由IBM开发。SQL语言分为3种类型:

#1、DDL语句    数据库定义语言: 数据库、表、视图、索引、存储过程,例如CREATE DROP ALTER
#2、DML语句    数据库操纵语言: 插入数据INSERT、删除数据DELETE、更新数据UPDATE、查询数据SELECT
#3、DCL语句    数据库控制语言: 例如控制用户的访问权限GRANT、REVOKE

关闭服务端 net stop MySQL
启动服务端 net start MySQL

基本操作

增 create database db1 charset utf8;
查 show databases;
   show create database db1;
改 alter database db1 charset gbk;
删 drop database db1
查看所在库 select database();
切换库 use db1;
增 creat table t1(id int, name char);
查 show tables;
   show create table t1;
   desc t1; 查看表结构
改 alter table t1 add sex char; 添加字段
   alter table t1 drop sex; 删除字段
   alter table t1 modify name char(8); 修改字段类型
   alter table t1 change name Name char(16); 修改原字段名及该字段类型
删 drop table t1;
  • 记录

增 insert into db1.t1(id,name) values 
   (1,'xionger'),(2,'xiongda');
查 select id,name from db1.t1  查指定字段
   select * from db1.t1  查所有(不推荐使用)
改 update t1 set name='DD' where id=2;
删 delete from t1 where id=2; 删除指定字段记录
   truncate t1; 清空表中记录(重置整张表)

 

表相关操作

存储引擎

存储引擎即表类型,mysql根据不同的表类型会有不同的处理机制

Innodb : 默认的存储引擎,查询速度相对myisam慢,但是更安全 特点是支持行锁,支持外键

innodb类型表有两个表文件
.frm : 表结构相关
.ibd : 数据相关 (innodb的索引就是用数据组织的,以主键为依据组织数据,用树型结构减少IO优化查询)

myisam : 老版本的存储引擎

myisam类型表有三个表文件
.frm ; 表结构相关
.MYD : 数据相关
.MYI : 索引文件

memory : 内存引擎,数据全部存在内存中,断电数据消失

.frm : 表结构相关

blackhole : 黑洞引擎,无论存什么数据,立马消失

.frm : 表结构相关

查看MySQL支持的存储引擎

show engines\G
查看正在使用的存储引擎
show variables like 'storage_engine%';
创建表时指定存储引擎
create table t1(id int)engine=innodb;

语法

  • 创建表

create table 表名(
    字段名1 类型[(宽度) 约束条件],
    字段名2 类型[(宽度) 约束条件],
    字段名3 类型[(宽度) 约束条件]
)
  • 1. 在同一张表中,字段名是不能相同
  • 2. 宽度和约束条件可选
  • 3. 字段名和类型是必须的
  • 修改表

修改表名
ALTER TABLE 表名 RENAME 新表名;
增加字段
ALTER TABLE 表名 
                ADD 字段名  数据类型 [完整性约束条件…],
                ADD 字段名  数据类型 [完整性约束条件…];
ALTER TABLE 表名 ADD 字段名  数据类型 [完整性约束条件…]  FIRST;
ALTER TABLE 表名 ADD 字段名  数据类型 [完整性约束条件…]  AFTER 字段名;
删除字段
ALTER TABLE 表名 DROP 字段名;
修改字段
ALTER TABLE 表名 MODIFY  字段名 数据类型 [完整性约束条件…];
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 旧数据类型 [完整性约束条件…];
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 新数据类型 [完整性约束条件…];
  • 复制表

复制表结构+记录 (key不会复制: 主键、外键和索引)
create table t2 select * from t1;
只复制表结构
select * from service where 1=2;  条件为假,查不到任何记录
reate table t4 like employees;

类型

  • 数值类型

整型 
TINYINT SMALLINT MEDIUMINT INT BIGINT
为该类型指定宽度时,仅仅只是指定查询结果的显示宽度,与存储范围无关

 

浮点型
float[(M,D)] [UNSIGNED] [ZEROFILL]
定义:m是数字总个数,d是小数点后个数。m最大值为255,d最大值为30
精确度:随着小数的增多,精度变得不准确
​
double[(M,D)] [UNSIGNED] [ZEROFILL]
定义:m是数字总个数,d是小数点后个数。m最大值为255,d最大值为30
精确度:随着小数的增多,精度比float要高,但也会变得不准确
​
decimal[(m[,d])] [unsigned] [zerofill]
定义: 准确的小数值,m是数字总个数(负号不算),d是小数点后个数。 m最大值为65,d最大值为30。
精确度: 随着小数的增多,精度始终准确,对于精确数值计算时需要用此类型,decaimal能够存储精确值的原因在于其内部按照字符串存储。
日期类型
YEAR 年
DATE 年-月-日
TIME 时:分:秒
DATETIME 年-月-日 时:分:秒
  • 字符串类型

char : 定长,数据超出预定长度报错,不够用空格补位
    - 特点: 查询速度快,单浪费空间
    - 检索:在检索或者说查询时,查出的结果会自动删除尾部的空格,除非我们打开pad_char_to_full_length SQL模式(SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';)
    - 注意:精准查找时(select * from user where name='xionger';),char类型补充的空格会自动去掉进行匹配,但是用like模糊查找时(select * from user name like 'xionger';),char类型补充的空格也会进行匹配
varchar : 变长,数据超出预定长度报错,不够就是实际长度
    - 特点: 精准,节省空间,查询较慢
    - 检索:尾部有空格会保存下来,在检索或者说查询时,也会正常显示包含空格在内的内容
​
查看字段长度 : char_length(字段)
    select char_length(name) from user;
  • 集合与枚举类型

枚举enum: 多选一
集合set: 多选多

约束条件

约束条件与数据类型的宽度一样,都是可选参数

作用:用于保证数据的完整性和一致性

PRIMARY KEY (PK)    标识该字段为该表的主键,可以唯一的标识记录
FOREIGN KEY (FK)    标识该字段为该表的外键
NOT NULL    标识该字段不能为空
UNIQUE KEY (UK)    标识该字段的值是唯一的
AUTO_INCREMENT    标识该字段的值自动增长(整数类型,而且为主键)
DEFAULT    为该字段设置默认值
​
UNSIGNED 无符号
ZEROFILL 使用0填充
  • not null / default

not null - 不可空
null - 可空
default 默认值
创建列时可以指定默认值,当插入数据时如果未主动设置,则自动添加默认值
create table user(
    id int,
    name char(16) not null,
    sex char(6) not null default "male"
); 
  • unique

单列唯一
create table user(
    id int unique,
    name char(16)
);
联合唯一
create table server(
    id int unique,
    ip char(15),
    port int,
    ip port,unique(ip,port)
)
  • primary key

从约束角度看: 主键等于not null + unique
1.一张表中有且有一个主键
2.若没有设置主键则会由上到下检索非空且唯一的字段作为主键
3.若没有主键也没有非空且唯一的字段,就采用默认的隐藏字段作为主键(7个bytes),这样丧失了查询效率
innodb类要依据主键组织数据结构(idb文件)
索引的目的是一步步缩小查询范围,减少IO次数
  • auto_increment

1.auto_increment通常与primary key连用
2.auto_increment通常加给id字段
3.auto_increment只能给被定义成key(unique key,primary key)的字段加

表关系

所有数据在一张表中导致: 组织结构不清晰,扩展性差,浪费空间

foreign key 外键是一种约束,约束两张表的关系

约束1:创建表 先建立被关联表,才能建关联表
约束2:查数据 被关联表先插入数据,关联表才能插入数据
约束3:删数据 先删除关联表中的数据,才能删被关联表的数据
约束4:不能改关联字段 

级联: 同步更新,同步删除

on update cascade # 同步更新
on delete cascade # 同步删除
注: 级联是绑定给外键的

多对一:

create table dep(
    id int primary key auto_increment,
    dep_name char(16),
    dep_comment char(64)
);
create table emp(
    id int primary key auto_increment,
    name char(16),
    gender enum('male','female') not null default 'male',
    dep_id int,
    foreign key(dep_id) references dep(id) 
    on update cascade # 同步更新 
    on delete cascade # 同步删除
);

多对多:

create table author(
    id int primary key auto_increment,
    name varchar(20)
);
create table book(
    id int primary key auto_increment,
    name char(16),
    price int
);
​# 创建第三张表
create table author2book(
    id int not null unique auto_increment,
    author_id int not null,
    book_id int not null,
    fk_author foreign key(author_id) references author(id) on delete cascade on update cascade,
    fk_book foreign key(book_id) references book(id) on delete cascade on update cascade,
    primary key(author_id,book_id)
);

 

表查询

单表查询

create table emp(
id int not null unique auto_increment,
name varchar(20) not null,
sex enum('male','female') not null default 'male', #大部分是男的
age int(3) unsigned not null default 28,
hire_date date not null,
post varchar(50),
post_comment varchar(100),
salary double(15,2),
office int, #一个部门一个屋子
depart_id int
);

#查看表结构
mysql> desc emp;
+--------------+-----------------------+------+-----+---------+----------------+
| Field        | Type                  | Null | Key | Default | Extra          |
+--------------+-----------------------+------+-----+---------+----------------+
| id           | int(11)               | NO   | PRI | NULL    | auto_increment |
| name         | varchar(20)           | NO   |     | NULL    |                |
| sex          | enum('male','female') | NO   |     | male    |                |
| age          | int(3) unsigned       | NO   |     | 28      |                |
| hire_date    | date                  | NO   |     | NULL    |                |
| post         | varchar(50)           | YES  |     | NULL    |                |
| post_comment | varchar(100)          | YES  |     | NULL    |                |
| salary       | double(15,2)          | YES  |     | NULL    |                |
| office       | int(11)               | YES  |     | NULL    |                |
| depart_id    | int(11)               | YES  |     | NULL    |                |
+--------------+-----------------------+------+-----+---------+----------------+

#插入记录
#三个部门:教学,销售,运营
insert into emp(name,sex,age,hire_date,post,salary,office,depart_id) values
('egon','male',18,'20170301','老男孩驻沙河办事处外交大使',7300.33,401,1), #以下是教学部
('alex','male',78,'20150302','teacher',1000000.31,401,1),
('wupeiqi','male',81,'20130305','teacher',8300,401,1),
('yuanhao','male',73,'20140701','teacher',3500,401,1),
('liwenzhou','male',28,'20121101','teacher',2100,401,1),
('jingliyang','female',18,'20110211','teacher',9000,401,1),
('jinxin','male',18,'19000301','teacher',30000,401,1),
('成龙','male',48,'20101111','teacher',10000,401,1),

('歪歪','female',48,'20150311','sale',3000.13,402,2),#以下是销售部门
('丫丫','female',38,'20101101','sale',2000.35,402,2),
('丁丁','female',18,'20110312','sale',1000.37,402,2),
('星星','female',18,'20160513','sale',3000.29,402,2),
('格格','female',28,'20170127','sale',4000.33,402,2),

('张野','male',28,'20160311','operation',10000.13,403,3), #以下是运营部门
('程咬金','male',18,'19970312','operation',20000,403,3),
('程咬银','female',18,'20130311','operation',19000,403,3),
('程咬铜','male',18,'20150411','operation',18000,403,3),
('程咬铁','female',18,'20140512','operation',17000,403,3)
;
案例表信息

 

较完整的查询语句
select id,name from emp
    where id > 1 and name like %xx%
    group by city
    having 分组后的条件
    order by 排序依据
    limit 展示条数;
  • DISTINCT 去重查询

查出所有的岗位(去掉重复)
SELECT DISTINCT post FROM emp;
+--------------------+
| post               |
+--------------------+
| 张江第一帅形象代言 |
| teacher            |
| sale               |
| operation          |
+--------------------+
结果
  • 四则运行查询

查年薪,重命名
SELECT name, salary*12 FROM emp;
SELECT name, salary*12 AS year_salary FROM emp;
+--------+-------------+
| name   | year_salary |
+--------+-------------+
| jason  |    87603.96 |
| egon   | 12000003.72 |
| kevin  |    99600.00 |
| tank   |    42000.00 |
| owen   |    25200.00 |
| jerry  |   108000.00 |
| nick   |   360000.00 |
| sean   |   120000.00 |
| 歪歪   |    36001.56 |
| 丫丫   |    24004.20 |
| 丁丁   |    12004.44 |
| 星星   |    36003.48 |
| 格格   |    48003.96 |
| 张野   |   120001.56 |
| 程咬金 |   240000.00 |
| 程咬银 |   228000.00 |
| 程咬铜 |   216000.00 |
| 程咬铁 |   204000.00 |
+--------+-------------+
结果
  • CONCAT 定义显式

查出所有员工的名字,薪资,格式为:
    <名字:xxx>    <薪资:666666>
SELECT CONCAT('姓名: ',name,'  年薪: ', salary*12)  AS year_salary FROM emp;
+-------------------------------+
| year_salary                   |
+-------------------------------+
| 姓名: jason  年薪: 87603.96   |
| 姓名: egon  年薪: 12000003.72 |
| 姓名: kevin  年薪: 99600.00   |
| 姓名: tank  年薪: 42000.00    |
| 姓名: owen  年薪: 25200.00    |
| 姓名: jerry  年薪: 108000.00  |
| 姓名: nick  年薪: 360000.00   |
| 姓名: sean  年薪: 120000.00   |
| 姓名: 歪歪  年薪: 36001.56    |
| 姓名: 丫丫  年薪: 24004.20    |
| 姓名: 丁丁  年薪: 12004.44    |
| 姓名: 星星  年薪: 36003.48    |
| 姓名: 格格  年薪: 48003.96    |
| 姓名: 张野  年薪: 120001.56   |
| 姓名: 程咬金  年薪: 240000.00 |
| 姓名: 程咬银  年薪: 228000.00 |
| 姓名: 程咬铜  年薪: 216000.00 |
| 姓名: 程咬铁  年薪: 204000.00 |
+-------------------------------+
结果
  •  WHERE 约束

where字句中可以使用:

1. 比较运算符:> < >= <= <> !=
2. between 80 and 100 值在80到100之间
3. in(80,90,100) 值是10或20或30
4. like 'xxx%'
    pattern可以是%或_,
    %表示任意多字符
    _表示一个字符 
5. 逻辑运算符:多个条件直接可以使用逻辑运算符 and or not

1.查看岗位是teacher的员工姓名、年龄
select name,age from emp where post = 'teacher';
+-------+-----+
| name  | age |
+-------+-----+
| egon  |  78 |
| kevin |  81 |
| tank  |  73 |
| owen  |  28 |
| jerry |  18 |
| nick  |  18 |
| sean  |  48 |
+-------+-----+
结果
2.查看岗位是teacher且年龄大于30岁的员工姓名、年龄
select name,age from emp where post='teacher' and age > 30; 
+-------+-----+
| name  | age |
+-------+-----+
| egon  |  78 |
| kevin |  81 |
| tank  |  73 |
| sean  |  48 |
+-------+-----+
结果
3. 查看岗位是teacher且薪资在9000-1000范围内的员工姓名、年龄、薪资
select name,age,salary from emp where post='teacher' and salary between 9000 and 10000;
+-------+-----+----------+
| name  | age | salary   |
+-------+-----+----------+
| jerry |  18 |  9000.00 |
| sean  |  48 | 10000.00 |
+-------+-----+----------+
结果
4. 查看岗位描述不为NULL的员工信息
select * from emp where post_comment is not null;
Empty set (0.00 sec)
结果
5. 查看岗位是teacher且薪资是10000或9000或30000的员工姓名、年龄、薪资
select name,age,salary from emp where post='teacher' and salary in (10000,9000,30000);
+-------+-----+----------+
| name  | age | salary   |
+-------+-----+----------+
| jerry |  18 |  9000.00 |
| nick  |  18 | 30000.00 |
| sean  |  48 | 10000.00 |
+-------+-----+----------+
结果
6. 查看岗位是teacher且薪资不是10000或9000或30000的员工姓名、年龄、薪资
select name,age,salary from emp where post='teacher' and salary not in (10000,9000,30000);
+-------+-----+------------+
| name  | age | salary     |
+-------+-----+------------+
| egon  |  78 | 1000000.31 |
| kevin |  81 |    8300.00 |
| tank  |  73 |    3500.00 |
| owen  |  28 |    2100.00 |
+-------+-----+------------+
结果
7. 查看岗位是teacher且名字是jin开头的员工姓名、年薪
select name,salary*12 from emp where post='teacher' and name like 'j%';
+-------+-----------+
| name  | salary*12 |
+-------+-----------+
| jerry | 108000.00 |
+-------+-----------+
结果
  • GROUP BY 分组查询

1、首先明确一点:分组发生在where之后,即分组是基于where之后得到的记录而进行的

2、分组指的是:将所有记录按照某个相同字段进行归类,比如针对员工信息表的职位分组,或者按照性别进行分组等

3、大前提: 可以按照任意字段分组,但是分组完毕后,比如group by post,只能查看post字段,如果想查看组内信息,需要借助于聚合函数

#查看MySQL 5.7默认的sql_mode如下:
mysql> select @@global.sql_mode;
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

#!!!注意
ONLY_FULL_GROUP_BY的语义就是确定select target list中的所有列的值都是明确语义,简单的说来,在ONLY_FULL_GROUP_BY模式下,target list中的值要么是来自于聚集函数的结果,要么是来自于group by list中的表达式的值。


#设置sql_mole如下操作(我们可以去掉ONLY_FULL_GROUP_BY模式):
mysql> set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

mysql> select @@global.sql_mode;
+-------------------+
| @@global.sql_mode |
+-------------------+
|                   |
+-------------------+
1 row in set (0.00 sec)

mysql> select * from emp group by post; 
+----+------+--------+-----+------------+----------------------------+--------------+------------+--------+-----------+
| id | name | sex    | age | hire_date  | post                       | post_comment | salary     | office | depart_id |
+----+------+--------+-----+------------+----------------------------+--------------+------------+--------+-----------+
| 14 | 张野 | male   |  28 | 2016-03-11 | operation                  | NULL         |   10000.13 |    403 |         3 |
|  9 | 歪歪 | female |  48 | 2015-03-11 | sale                       | NULL         |    3000.13 |    402 |         2 |
|  2 | alex | male   |  78 | 2015-03-02 | teacher                    | NULL         | 1000000.31 |    401 |         1 |
|  1 | egon | male   |  18 | 2017-03-01 | 老男孩驻沙河办事处外交大使 | NULL         |    7300.33 |    401 |         1 |
+----+------+--------+-----+------------+----------------------------+--------------+------------+--------+-----------+
4 rows in set (0.00 sec)


#由于没有设置ONLY_FULL_GROUP_BY,于是也可以有结果,默认都是组内的第一条记录,但其实这是没有意义的

mysql> set global sql_mode='ONLY_FULL_GROUP_BY';
Query OK, 0 rows affected (0.00 sec)

mysql> quit #设置成功后,一定要退出,然后重新登录方可生效
Bye

mysql> use db1;
Database changed
mysql> select * from emp group by post; #报错
ERROR 1055 (42000): 'db1.emp.id' isn't in GROUP BY
mysql> select post,count(id) from emp group by post; #只能查看分组依据和使用聚合函数
+----------------------------+-----------+
| post                       | count(id) |
+----------------------------+-----------+
| operation                  |         5 |
| sale                       |         5 |
| teacher                    |         7 |
| 老男孩驻沙河办事处外交大使 |         1 |
+----------------------------+-----------+
4 rows in set (0.00 sec)
ONLY_FULL_GROUP_BY

 

单独使用GROUP BY关键字分组
    SELECT post FROM emp GROUP BY post;
    注意:我们按照post字段分组,那么select查询的字段只能是post,想要获取组内的其他相关信息,需要借助函数

GROUP BY关键字和GROUP_CONCAT()函数一起使用
    SELECT post,GROUP_CONCAT(name) FROM emp GROUP BY post;#按照岗位分组,并查看组内成员名
    SELECT post,GROUP_CONCAT(name) as emp_members FROM emp GROUP BY post;

GROUP BY与聚合函数一起使用
    select post,count(id) as count from emp group by post;#按照岗位分组,并查看每个组有多少人
如果我们用unique的字段作为分组的依据,则每一条记录自成一组,这种分组没有意义
多条记录之间的某个字段值相同,该字段通常用来作为分组的依据
  • 聚合函数

#强调:聚合函数聚合的是组的内容,若是没有分组,则默认一组

示例:
    SELECT COUNT(*) FROM emp;
    SELECT COUNT(*) FROM empe WHERE depart_id=1;
    SELECT MAX(salary) FROM emp;
    SELECT MIN(salary) FROM emp;
    SELECT AVG(salary) FROM emp;
    SELECT SUM(salary) FROM emp;
    SELECT SUM(salary) FROM emp WHERE depart_id=3;
1. 查询岗位名以及岗位包含的所有员工名字
select post,group_concat(name) from emp group by post;
+--------------------+--------------------------------------+
| post               | group_concat(name)                   |
+--------------------+--------------------------------------+
| operation          | 张野,程咬金,程咬银,程咬铜,程咬铁     |
| sale               | 歪歪,丫丫,丁丁,星星,格格             |
| teacher            | egon,kevin,tank,owen,jerry,nick,sean |
| 张江第一帅形象代言 | jason                                |
+--------------------+--------------------------------------+
结果
2. 查询岗位名以及各岗位内包含的员工个数
select post,count(id) from emp group by post;
+--------------------+-----------+
| post               | count(id) |
+--------------------+-----------+
| operation          |         5 |
| sale               |         5 |
| teacher            |         7 |
| 张江第一帅形象代言 |         1 |
+--------------------+-----------+
结果
3.查询公司内男员工和女员工的个数
select gender,count(id) from emp group by gender;
+--------+-----------+
| gender | count(id) |
+--------+-----------+
| male   |        10 |
| female |         8 |
+--------+-----------+
结果
4. 查询岗位名以及各岗位的平均薪资
select post,avg(salary) from emp group by post;
+--------------------+---------------+
| post               | avg(salary)   |
+--------------------+---------------+
| operation          |  16800.026000 |
| sale               |   2600.294000 |
| teacher            | 151842.901429 |
| 张江第一帅形象代言 |   7300.330000 |
+--------------------+---------------+
结果
5. 查询岗位名以及各岗位的最高薪资
select post,max(salary) from emp group by post;
+--------------------+-------------+
| post               | max(salary) |
+--------------------+-------------+
| operation          |    20000.00 |
| sale               |     4000.33 |
| teacher            |  1000000.31 |
| 张江第一帅形象代言 |     7300.33 |
+--------------------+-------------+
结果
6. 查询岗位名以及各岗位的最低薪资
select post,min(salary) from emp group by post;
+--------------------+-------------+
| post               | min(salary) |
+--------------------+-------------+
| operation          |    10000.13 |
| sale               |     1000.37 |
| teacher            |     2100.00 |
| 张江第一帅形象代言 |     7300.33 |
结果
7. 查询男员工与男员工的平均薪资,女员工与女员工的平均薪资
select gender,avg(salary) from emp group by gender;
+--------+---------------+
| gender | avg(salary)   |
+--------+---------------+
| male   | 110920.077000 |
| female |   7250.183750 |
+--------+---------------+
结果
  • HAVING 分组后过滤

HAVING与WHERE不一样的地方在于!!!!!!

执行优先级从高到低:where > group by > having 
1. Where 发生在分组group by之前,因而Where中可以有任意字段,但是绝对不能使用聚合函数。
2. Having发生在分组group by之后,因而Having中可以使用分组的字段,无法直接取到其他字段,可以使用聚合函数
1. 查询各岗位内包含的员工个数小于2的岗位名、岗位内包含员工名字、个数
select post,group_concat(name),count(id) from emp group by post having count(id) < 2;
+--------------------+--------------------+-----------+
| post               | group_concat(name) | count(id) |
+--------------------+--------------------+-----------+
| 张江第一帅形象代言 | jason              |         1 |
+--------------------+--------------------+-----------+
结果
2. 查询各岗位平均薪资大于10000的岗位名、平均工资
select post,avg(salary) from emp group by post having avg(salary) > 10000;
+-----------+---------------+
| post      | avg(salary)   |
+-----------+---------------+
| operation |  16800.026000 |
| teacher   | 151842.901429 |
+-----------+---------------+
结果
3. 查询各岗位平均薪资大于10000且小于20000的岗位名、平均工资
select post,avg(salary) from emp group by post having avg(salary) > 10000 and avg(salary) <20000;
+-----------+--------------+
| post      | avg(salary)  |
+-----------+--------------+
| operation | 16800.026000 |
+-----------+--------------+
结果
  • ORDER BY 排序

正序 ASC 默认

倒序 DESC

1. 查询所有员工信息,先按照age升序排序,如果age相同则按照hire_date降序排序
select * from emp ORDER BY age asc,hire_date desc;
+----+--------+--------+-----+------------+--------------------+--------------+------------+--------+-----------+
| id | name   | gender | age | hire_date  | post               | post_comment | salary     | office | depart_id |
+----+--------+--------+-----+------------+--------------------+--------------+------------+--------+-----------+
|  1 | jason  | male   |  18 | 2017-03-01 | 张江第一帅形象代言 | NULL         |    7300.33 |    401 |         1 |
| 12 | 星星   | female |  18 | 2016-05-13 | sale               | NULL         |    3000.29 |    402 |         2 |
| 17 | 程咬铜 | male   |  18 | 2015-04-11 | operation          | NULL         |   18000.00 |    403 |         3 |
| 18 | 程咬铁 | female |  18 | 2014-05-12 | operation          | NULL         |   17000.00 |    403 |         3 |
| 16 | 程咬银 | female |  18 | 2013-03-11 | operation          | NULL         |   19000.00 |    403 |         3 |
| 11 | 丁丁   | female |  18 | 2011-03-12 | sale               | NULL         |    1000.37 |    402 |         2 |
|  6 | jerry  | female |  18 | 2011-02-11 | teacher            | NULL         |    9000.00 |    401 |         1 |
| 15 | 程咬金 | male   |  18 | 1997-03-12 | operation          | NULL         |   20000.00 |    403 |         3 |
|  7 | nick   | male   |  18 | 1900-03-01 | teacher            | NULL         |   30000.00 |    401 |         1 |
| 13 | 格格   | female |  28 | 2017-01-27 | sale               | NULL         |    4000.33 |    402 |         2 |
| 14 | 张野   | male   |  28 | 2016-03-11 | operation          | NULL         |   10000.13 |    403 |         3 |
|  5 | owen   | male   |  28 | 2012-11-01 | teacher            | NULL         |    2100.00 |    401 |         1 |
| 10 | 丫丫   | female |  38 | 2010-11-01 | sale               | NULL         |    2000.35 |    402 |         2 |
|  9 | 歪歪   | female |  48 | 2015-03-11 | sale               | NULL         |    3000.13 |    402 |         2 |
|  8 | sean   | male   |  48 | 2010-11-11 | teacher            | NULL         |   10000.00 |    401 |         1 |
|  4 | tank   | male   |  73 | 2014-07-01 | teacher            | NULL         |    3500.00 |    401 |         1 |
|  2 | egon   | male   |  78 | 2015-03-02 | teacher            | NULL         | 1000000.31 |    401 |         1 |
|  3 | kevin  | male   |  81 | 2013-03-05 | teacher            | NULL         |    8300.00 |    401 |         1 |
+----+--------+--------+-----+------------+--------------------+--------------+------------+--------+-----------+
结果
2. 查询各岗位平均薪资大于10000的岗位名、平均工资,结果按平均薪资升序排列
select post,avg(salary) from emp group by post having avg(salary) > 10000 order by avg(salary) asc;
+-----------+---------------+
| post      | avg(salary)   |
+-----------+---------------+
| operation |  16800.026000 |
| teacher   | 151842.901429 |
+-----------+---------------+
结果
3. 查询各岗位平均薪资大于10000的岗位名、平均工资,结果按平均薪资降序排列
select post,avg(salary) from emp group by post having avg(salary) > 10000 order by avg(salary) desc;
+-----------+---------------+
| post      | avg(salary)   |
+-----------+---------------+
| teacher   | 151842.901429 |
| operation |  16800.026000 |
+-----------+---------------+
结果
  • LIMIT 限制查询记录的条数

示例:
    SELECT * FROM emp ORDER BY salary DESC 
        LIMIT 3;                    #默认初始位置为0 
    
    SELECT * FROM emp ORDER BY salary DESC
        LIMIT 0,5; #从第0开始,即先查询出第一条,然后包含这一条在内往后查5条

    SELECT * FROM emp ORDER BY salary DESC
        LIMIT 5,5; #从第5开始,即先查询出第6条,然后包含这一条在内往后查5条
  •  单表查询关键字执行顺序

执行顺序:
from    # 确定是那张表
where   # 根据条件,筛选数据
group by    # 分组
having  # 对分组后的表筛选 分组之后只能拿到分组的依据和聚合函数的结果
select  # 拿出筛选出来的数据中的某些字段
distinct  # 去重

多表查询

create table dep(
id int,
name varchar(20) 
);

create table emp(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') not null default 'male',
age int,
dep_id int
);

#插入数据
insert into dep values
(200,'技术'),
(201,'人力资源'),
(202,'销售'),
(203,'运营');

insert into emp(name,sex,age,dep_id) values
('egon','male',18,200),
('alex','female',48,201),
('wupeiqi','male',38,201),
('yuanhao','female',28,202),
('liwenzhou','male',18,200),
('jingliyang','female',18,204)
;

#查看表结构和数据
mysql> desc dep;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+

mysql> desc emp;
+--------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-----------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| sex | enum('male','female') | NO | | male | |
| age | int(11) | YES | | NULL | |
| dep_id | int(11) | YES | | NULL | |
+--------+-----------------------+------+-----+---------+----------------+

mysql> select * from dep;
+------+--------------+
| id | name |
+------+--------------+
| 200 | 技术 |
| 201 | 人力资源 |
| 202 | 销售 |
| 203 | 运营 |
+------+--------------+

mysql> select * from emp;
+----+------------+--------+------+--------+
| id | name | sex | age | dep_id |
+----+------------+--------+------+--------+
| 1 | egon | male | 18 | 200 |
| 2 | alex | female | 48 | 201 |
| 3 | wupeiqi | male | 38 | 201 |
| 4 | yuanhao | female | 28 | 202 |
| 5 | liwenzhou | male | 18 | 200 |
| 6 | jingliyang | female | 18 | 204 |
+----+------------+--------+------+--------+
案例表信息
  •  笛卡尔积

 左表的一条记录对应右表的每条记录,其中一条记录是正确的对应关系

select * from emp,dep;
+----+------------+--------+------+--------+------+--------------+
| id | name       | sex    | age  | dep_id | id   | name         |
+----+------------+--------+------+--------+------+--------------+
|  1 | egon       | male   |   18 |    200 |  200 | 技术         |
|  1 | egon       | male   |   18 |    200 |  201 | 人力资源     |
|  1 | egon       | male   |   18 |    200 |  202 | 销售         |
|  1 | egon       | male   |   18 |    200 |  203 | 运营         |
|  2 | alex       | female |   48 |    201 |  200 | 技术         |
|  2 | alex       | female |   48 |    201 |  201 | 人力资源     |
|  2 | alex       | female |   48 |    201 |  202 | 销售         |
|  2 | alex       | female |   48 |    201 |  203 | 运营         |
|  3 | wupeiqi    | male   |   38 |    201 |  200 | 技术         |
|  3 | wupeiqi    | male   |   38 |    201 |  201 | 人力资源     |
|  3 | wupeiqi    | male   |   38 |    201 |  202 | 销售         |
|  3 | wupeiqi    | male   |   38 |    201 |  203 | 运营         |
|  4 | yuanhao    | female |   28 |    202 |  200 | 技术         |
|  4 | yuanhao    | female |   28 |    202 |  201 | 人力资源     |
|  4 | yuanhao    | female |   28 |    202 |  202 | 销售         |
|  4 | yuanhao    | female |   28 |    202 |  203 | 运营         |
|  5 | liwenzhou  | male   |   18 |    200 |  200 | 技术         |
|  5 | liwenzhou  | male   |   18 |    200 |  201 | 人力资源     |
|  5 | liwenzhou  | male   |   18 |    200 |  202 | 销售         |
|  5 | liwenzhou  | male   |   18 |    200 |  203 | 运营         |
|  6 | jingliyang | female |   18 |    204 |  200 | 技术         |
|  6 | jingliyang | female |   18 |    204 |  201 | 人力资源     |
|  6 | jingliyang | female |   18 |    204 |  202 | 销售         |
|  6 | jingliyang | female |   18 |    204 |  203 | 运营         |
+----+------------+--------+------+--------+------+--------------+
结果

可以利用where条件选出正确的对应关系,正常不用where做链表的活

select * from emp,dep where emp.dep_id = dep.id;
+----+-----------+--------+------+--------+------+--------------+
| id | name      | sex    | age  | dep_id | id   | name         |
+----+-----------+--------+------+--------+------+--------------+
|  1 | egon      | male   |   18 |    200 |  200 | 技术         |
|  2 | alex      | female |   48 |    201 |  201 | 人力资源     |
|  3 | wupeiqi   | male   |   38 |    201 |  201 | 人力资源     |
|  4 | yuanhao   | female |   28 |    202 |  202 | 销售         |
|  5 | liwenzhou | male   |   18 |    200 |  200 | 技术         |
+----+-----------+--------+------+--------+------+--------------+
结果
  •  内连接 inner join ... on ...

 只取两张表有对应关系的记录,链接成一张虚拟表

select * from emp inner join dep on emp.dep_id = dep.id;
+----+-----------+--------+------+--------+------+--------------+
| id | name      | sex    | age  | dep_id | id   | name         |
+----+-----------+--------+------+--------+------+--------------+
|  1 | egon      | male   |   18 |    200 |  200 | 技术         |
|  2 | alex      | female |   48 |    201 |  201 | 人力资源     |
|  3 | wupeiqi   | male   |   38 |    201 |  201 | 人力资源     |
|  4 | yuanhao   | female |   28 |    202 |  202 | 销售         |
|  5 | liwenzhou | male   |   18 |    200 |  200 | 技术         |
+----+-----------+--------+------+--------+------+--------------+
结果
查询"技术"部门员工的信息
select * from emp inner join dep on emp.dep_id = dep.id 
    where dep.name = "技术";
+----+-----------+------+------+--------+------+--------+
| id | name      | sex  | age  | dep_id | id   | name   |
+----+-----------+------+------+--------+------+--------+
|  1 | egon      | male |   18 |    200 |  200 | 技术   |
|  5 | liwenzhou | male |   18 |    200 |  200 | 技术   |
+----+-----------+------+------+--------+------+--------+
结果
  • 左连接 left join ... on ...

内连接基础上,保留左表没有对应关系的记录

select * from emp left join dep on emp.dep_id = dep.id;
+----+------------+--------+------+--------+------+--------------+
| id | name       | sex    | age  | dep_id | id   | name         |
+----+------------+--------+------+--------+------+--------------+
|  1 | egon       | male   |   18 |    200 |  200 | 技术         |
|  5 | liwenzhou  | male   |   18 |    200 |  200 | 技术         |
|  2 | alex       | female |   48 |    201 |  201 | 人力资源     |
|  3 | wupeiqi    | male   |   38 |    201 |  201 | 人力资源     |
|  4 | yuanhao    | female |   28 |    202 |  202 | 销售         |
|  6 | jingliyang | female |   18 |    204 | NULL | NULL         |
+----+------------+--------+------+--------+------+--------------+
结果
  • 右链接 right join ... on ...

内连接基础上,保留右表没有对应关系的记录

select * from emp right join dep on emp.dep_id = dep.id;
+------+-----------+--------+------+--------+------+--------------+
| id   | name      | sex    | age  | dep_id | id   | name         |
+------+-----------+--------+------+--------+------+--------------+
|    1 | egon      | male   |   18 |    200 |  200 | 技术         |
|    2 | alex      | female |   48 |    201 |  201 | 人力资源     |
|    3 | wupeiqi   | male   |   38 |    201 |  201 | 人力资源     |
|    4 | yuanhao   | female |   28 |    202 |  202 | 销售         |
|    5 | liwenzhou | male   |   18 |    200 |  200 | 技术         |
| NULL | NULL      | NULL   | NULL |   NULL |  203 | 运营         |
+------+-----------+--------+------+--------+------+--------------+
结果
  • 全连接 union

内连接基础上,保留左右两张表没有对应关系的记录

 select * from emp inner join dep on emp.dep_id = dep.id
     union
 select * from emp left join dep on emp.dep_id = dep.id;
+----+------------+--------+------+--------+------+--------------+
| id | name       | sex    | age  | dep_id | id   | name         |
+----+------------+--------+------+--------+------+--------------+
|  1 | egon       | male   |   18 |    200 |  200 | 技术         |
|  2 | alex       | female |   48 |    201 |  201 | 人力资源     |
|  3 | wupeiqi    | male   |   38 |    201 |  201 | 人力资源     |
|  4 | yuanhao    | female |   28 |    202 |  202 | 销售         |
|  5 | liwenzhou  | male   |   18 |    200 |  200 | 技术         |
|  6 | jingliyang | female |   18 |    204 | NULL | NULL         |
+----+------------+--------+------+--------+------+--------------+
结果
  • 子查询

1:子查询是将一个查询语句嵌套在另一个查询语句中。

2:内层查询语句的查询结果,可以为外层查询语句提供查询条件

3:子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字

4:还可以包含比较运算符:= 、 !=、> 、<

查询技术部门员工的姓名:
1.链表查询:
select emp.name 
    from emp inner join dep on emp.dep_id = dep.id 
    where dep.name = "技术";
2.子查询: 
select name from emp 
    where dep_id = (
        select id from dep where name = "技术"
    );    
+-----------+
| name      |
+-----------+
| egon      |
| liwenzhou |
+-----------+
结果

 

查询平均年龄在25岁以上的部门名称
1.链表查询:
select dep.name from 
    emp inner join dep on emp.dep_id = dep.id 
    group by dep.name 
    having avg(age) > 25;
2.子查询:
select name from dep 
    where id in  (
        select dep_id from emp group by dep_id having avg(age) > 25
    );
+--------------+
| name         |
+--------------+
| 人力资源     |
| 销售         |
+--------------+
结果

带EXISTS关键字的子查询

EXISTS关字键字表示存在。在使用EXISTS关键字时,内层查询语句不返回查询的记录。
而是返回一个真假值。True或False
当返回True时,外层查询语句将进行查询;当返回值为False时,外层查询语句不进行查询

#dep表中存在dept_id=203,Ture
select * from emp
         where exists
             (select id from dep where id=200);
+----+------------+--------+------+--------+
| id | name       | sex    | age  | dep_id |
+----+------------+--------+------+--------+
|  1 | egon       | male   |   18 |    200 |
|  2 | alex       | female |   48 |    201 |
|  3 | wupeiqi    | male   |   38 |    201 |
|  4 | yuanhao    | female |   28 |    202 |
|  5 | liwenzhou  | male   |   18 |    200 |
|  6 | jingliyang | female |   18 |    204 |
+----+------------+--------+------+--------+
结果
#dep表中存在dept_id=205,False
select * from emp
        where exists
             (select id from dep where id=204);
Empty set (0.00 sec)
结果

 

PyMySQL

pymysql是一个socket客户端,使用它需要先建立连接

  • 基本使用

1.连接数据库

import pymysql
conn = pymysql.connect(
    host = '127.0.0.1',
    port = 3306,
    user = 'root',
    password = '',
    database = 'db1',
    charset = 'utf8',
)

2.获取游标

cursor = conn.cursor()
cursor = conn.cursor(pymysql.cursors.DictCursor)  
# 获取游标时,通常用此方法获取,这样查询返回的数据是字典的形式,
  1. key是字段,value是字段值
  2. 每个字典就是一条记录

游标就是cmd里的:

 

 3.向游标提交sql语句

rows = cursor.execute('show tables;')
print(rows)  # 2  得到的结果是响应的行数
补充: 当输入的sql语句的查询没有结果时,影响行数为0

 

我们在cmd里执行sql语句得到的是数据结果和行数,在python中执行的sql语句打印出来的只有行数,实际上数据结果也拿到了,此时在内存中,可以继续通过游标获取

4.获取数据

获取一条 : fetchone()
获取所有 : fetchall()
获取指定数量: fetchmany(size)
rows = cursor.execute('select * from dep')
print(rows)  # 4 
print(cursor.fetchone())  # {'id': 200, 'name': '技术'}
print(cursor.fetchmany(2))  # [{'id': 200, 'name': '技术'}, {'id': 201, 'name': '人力资源'}]
print(cursor.fetchall())  # [{'id':200, 'name': '技术'},{'id': 201, 'name': '人力资源'}, {'id': 202, 'name': '销售'}, {'id': 203, 'name': '运营'}]

5.关闭游标关闭socket连接通道

cursor.close()
conn.close()
  • 游标控制

absolute 绝对移动

cursor.scroll(2, 'absolute') # 相对于起始位置移动2位
print(cursor.fetchone())  # {'id': 202, 'name': '销售'}

relative 相对移动

cursor.scroll(3,'relative')  # 相对当前光标所在位置移动3位
print(cursor.fetchone())  # {'id': 203, 'name': '运营'}
  • sql注入问题

# 创建user表
create table user(
    id int primary key auto_increment,
    name char(16) not null unique,
    password char(16) not null
);
# 插入数据
insert into user(id, name, password) values(1, 'xiongda', 123), (2, 'xionger', 456)

# select * from user;
+----+---------+----------+
| id | name    | password |
+----+---------+----------+
|  1 | xiongda | 123      |
|  2 | xionger | 456      |
+----+---------+----------+
准备案例表

sql注入是利用sql的注释,or 等一些特殊字符,来改变sql的执行逻辑,从而使sql语句正常执行,得到数据.

cursor = conn.cursor(pymysql.cursors.DictCursor)

username = input(">>>:").strip()
password = input(">>>:").strip()

sql = "select * from user where name = '%s' and password = '%s'" %(username, password)

rows = cursor.execute(sql)
if rows:
    print('登录成功')
else:
    print('登录失败')

cursor.close()
conn.close()

>>>:xiongda' -- 1564as3d13a1sd 
>>>:
登录成功
>>>:xiongda' or 1=1 -- 1as32d13a2s1d
>>>:
登录成功

解决方法

原来我是自己对sql语句进行字符串拼接,导致sql注入问题

改写为利用execute帮助我们字符串拼接,pymysql帮我们处理了特殊符号

sql = "select * from user where name = %s and password = %s"
rows = cursor.execute(sql, [username, password])
  •  增、删、改:conn.commit()

增删改对于数据库来说都是敏感操作,提交完sql语句后都要加上conn.commit(),才能真正的对数据增删改

sql = "insert into user (name, password) values(%s, %s)"

rows = cursor.execute(sql, ['xxx', 789])
rows = cursor.executemany(sql, [('yyy',111), ('www', 321)])  # 一次插入多条数据
print(cursor.lastrowid)  # 当前记录是第几条
conn.commit()

也可以在连接数据库时配置autocommit = True,就不需要手动写conn.commit()

conn = pymysql.connect(
    host = '127.0.0.1',
    port = 3306,
    user = 'root',
    password = '',
    database = 'db1',
    charset = 'utf8',
    autocommit = True  # 这个参数配置后,增删改操作都不会需要手动加conn.commit了
)

 

视图

视图就是一张虚拟表,虚拟表都是通过查询得到的

使用视图我们可以把查询过程中的临时表摘出来,用视图去实现,这样以后再想操作该临时表的数据时就无需重写复杂的sql了,直接去视图中查找即可,但视图有明显地效率问题,并且视图是存放在数据库中的,如果我们程序中使用的sql过分依赖数据库中的视图,即强耦合,那就意味着扩展sql极为不便,因此并不推荐使用

create table course(
  cid int primary key auto_increment,
  cname char(20),
  teacher_id int
);
create table teacher(
  tid int primary key auto_increment,
  tname char(20)
);

insert into course(cname, teacher_id) values
    ('生物',1),
    ('物理',2),
    ('体育',3),
    ('美术',2);

insert into teacher(tname) values 
  ('张磊老师'),
  ('李平老师'),
  ('刘海燕老师'),
  ('朱云海老师'),
  ('李杰老师');

 select * from course;
+-----+--------+------------+
| cid | cname  | teacher_id |
+-----+--------+------------+
|   1 | 生物   |          1 |
|   2 | 物理   |          2 |
|   3 | 体育   |          3 |
|   4 | 美术   |          2 |
+-----+--------+------------+

select * from teacher;
+-----+-----------------+
| tid | tname           |
+-----+-----------------+
|   1 | 张磊老师        |
|   2 | 李平老师        |
|   3 | 刘海燕老师      |
|   4 | 朱云海老师      |
|   5 | 李杰老师        |
+-----+-----------------+
案例表
  • 创建视图

创建一张老师与课程内连接的虚拟表
create view course_teacher as
    select * from course inner join teacher on course.teacher_id = teacher.tid;
select * from course_teacher;
+-----+--------+------------+-----+-----------------+
| cid | cname  | teacher_id | tid | tname           |
+-----+--------+------------+-----+-----------------+
|   1 | 生物   |          1 |   1 | 张磊老师        |
|   2 | 物理   |          2 |   2 | 李平老师        |
|   3 | 体育   |          3 |   3 | 刘海燕老师      |
|   4 | 美术   |          2 |   2 | 李平老师        |
+-----+--------+------------+-----+-----------------+
结果

注意: 

1.在硬盘中虚拟表只有 .frm文件(表结构),没有 .idb文件(数据)

2.使用视图以后就无需每次都重写子查询的sql,但是这么效率并不高,还不如我们写子查询的效率高

3.视图通常用来辅助查询,不要修改视图中的数据!!!

  • 修改视图

ALTER VIEW 视图名称 AS SQL语句
  • 删除视图 

DROP VIEW 视图名称

 

存储过程

存储过程包含了一系列可执行的sql语句,存储过程放于MySQL中,通过调用它的名字可以执行其内部的一堆sql(像在对象里封装了一堆方法,直接用对象调用方法即可)

优点

1.用于替代程序写的sql语句,实现程序与sql解耦

2.给予网络传输,传别名的数据量小,而直接传sql数据量大

缺点

1.程序员扩展功能不方便

补充 

模型一:
应用程序:只需要开发应用程序的逻辑
mysql:编写好存储过程,以供应用程序调用
优点:开发效率执行效率都高
缺点:考虑到人为因素,跨部门沟通等问题,导致扩展性差

模型二:
应用程序:既要开发应用的逻辑,也要编写原生的sql
优点: 公司成本低
缺点: 开发效率执行效率不如方式一,编写原生sql过于复杂,还要考虑优化问题

模型三:
应用程序:只需要开发应用程序的逻辑,不需要编写原生sql,使用ORM框架
三种开发模式
  • 创建存储过程 procedure

create procedure 名(参数)
begin
    sql语句
end
  • 使用存储过程

无参数

delimiter $$
create procedure p1() begin select
* from user; end $$
delimiter ;
#在mysql中调用 call p1()
 call p1();
+----+---------+----------+
| id | name    | password |
+----+---------+----------+
|  1 | xiongda | 123      |
|  2 | xionger | 456      |
|  3 | xxx     | 789      |
+----+---------+----------+
结果

有参数

in 用于传入参数使用

out 用于返回值用

inout 既可以传入也可以当做返回值

delimiter $$
create procedure p2(
    in n int,
    in m int,
    out res int
)
begin
    select * from user where id > n and id < m;
    set res=0;
end $$

delimiter ;
#在mysql中调用 set @res=0; #0代表假(执行失败),1代表真(执行成功) call p2(1, 3, @res); # 注意:返回值只能接收变量,所以要先定义变量再传入 select @res;
 set @res=0; 

call p2(1, 3, @res);
+----+---------+----------+
| id | name    | password |
+----+---------+----------+
|  2 | xionger | 456      |
+----+---------+----------+

select @res;
+------+
| @res |
+------+
|    0 |
+------+
结果
  • python中调用存储过程 callproc

python中基于pymsql调用存储过程

游标.callproc(存储过程名, (参数们))

cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.callproc('p2',(1, 3, 1))  # @_p2_0=1,@_p2_1=3,@_p2_2=1,
print(cursor.fetchall())  # [{'id': 2, 'name': 'xionger', 'password': '456'}]

cursor.execute('select @_p2_2;')
print(cursor.fetchall())  # [{'@_p2_2': 0}]
  • 查看存储过程

show create procedure 名;
  • 删除存储过程

drop function 名;

索引    

mysql中存在一种专门的数据结构,key,又叫索引,通过该数据结构可以不断的缩小查询范围从而减少IO次数,达到加速查询效率目的
- index key : 只加速查询效果,没有约束功能
- unique key : 不仅有加速查询效果,还附加了约束功能
- primary key : 不仅有加速查询效果,还附加了约束功能,并且innodb存储引擎会按照主键字段的值来组织表中所有的数据,所以一张innodb表中有且只有一个主键,innodb的索引跟数据都放在idb表数据文件中

  •  索引的影响

当表中有数据再建索引,建索引的速度会慢,因为要扫描数据进行'归类'

当存在索引再插入数据,插数据的速度会慢,因为之前的索引结构需要重新编排.

所以索引可以加速查询,但会影响写入数据速度

  • 聚集索引(primary key)

聚集索引其实指的就是表的主键

特点:叶子结点放的一条条完整的记录

  • 辅助索引(unique,index)

只在辅助索引的叶子节点就已经找到了我们想要的数据

特点:叶子结点存放的是辅助索引字段对应的那条记录的主键的值(比如:按照name字段创建索引,那么叶子节点存放的是:{name对应的值:name所在的那条记录的主键值})

select name from user where name='xionger';

上述语句叫覆盖索引:只在辅助索引的叶子节点中就已经找到了所有我们想要的数据

select age from user where name='xionger';

上述语句叫非覆盖索引,虽然查询的时候命中了索引字段name,但是要查的是age字段,所以还需要利用主键才去查找

posted @ 2019-12-14 14:25  waller  阅读(173)  评论(0编辑  收藏  举报