mysql 基础

是什么 为什么 怎么玩
1、数据库简介
数据库(Database)是按照数据结构来组织、存储和管理数据的仓库
石头 王八壳 金属 竹简 纸张 计算机(速度: CPU 》 内存 》 硬盘)

Db 数据库 
dbms  数据库管理系统 
Mysql是一种数据库管理系统 dbms

2、Mysq简介l
数据库的分类:
在当今的互联网中,最常见的数据库模型主要是两种,即关系型数据库和非关系型数据库。mysql就是典型的关系型数据库。
关系型数据库的特点是将数据保存在不同的表中,再将这些表放入数据库中,而不是将所有数据统一放在数据库里,这样的设计增加了MySQL的读取速度,灵活性和可管理型也得到了很大提高,访问以及管理MySQL数据库的最常用标准化语言为SQL结构化查询语句。数据持久化存储在硬盘当中;
Mysql----地皮
(造): 数据库 ----- 表 ----- 数据

PS:
SQL: 结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,
用于存取数据以及查询、更新和管理关系数据库系统;同时也是数据库脚本文件的扩展名。

Mysql是软件
数据库需要自己创建, 然后做, 表,数据都需要我们来自己造好

3、关系型数据库设计规则
设计遵循ER模型和三范式

E    entity   代表实体的意思      对应到数据库当中的一张表     代表类
R    relationship   代表关系的意思  
三范式:1、列不能拆分     2、唯一标识    3、关系引用主键

4、数据表的设计(对应: 类)
在表中为了更加准确的存储数据,保证数据的正确有效,可以在创建表的时候,为表添加一些强制性的验证,包括数据字段的类型、约束。

1. 字段类型(对应于: 类的属性)
在mysql中包含的数据类型很多,这里主要列出来常用的几种

数字:int,decimal(小数的);
例如decimal(5,2)的意思是,最大5位数,其中小数2位,1.2和2.33都行,但10000.21就不行,超出位数了

字符串:char ,varchar,text

text存储比较多的字符串,比如商品的描述信息
char存储的是固定的字符串数据
varchar存储的是可变的数据
存储的是字符

char(8)存储的数据不满8个字符会在右侧自动补上空格字符–>"abcd "
使用场景
存手机号码固定的就可以使用char(11)

varchar(8)存储数据不满8个字符,不会自动空格字符–>“abcd”
例如存姓名用varchar(8)

日期:datetime,date,time 1987-07-24

布尔:bit

   bit(8)八个二进制位
bit表示一个位
存储性别的时候:
存储0或者1开销少

如果存储male和female开销大
两个状态存储的时间建议使用存储0和1方式
比如性别,数据是否删除

2. 约束–主键、非空、惟一,默认值,外键,自动增长
约束就是限制的条件
主键primary key;不能重复,唯一标识,物理的存储方式,速度快
一个表当中有且仅有一个主键

非空not null;比如要姓名不能为空,当保存为null的时候就会报错。
惟一unique;这个值是唯一的。有重复的了会报错(比如身份证)
默认default;如果不写就会有个默认值,这种叫默认,只有类型。
外键foreign key

5、数据库的安装命令
1.安装MySQL服务端和客户端
Sudo apt-get install mysql-server

  1. 检查mysql安装情况
    Ps -ajx|grep mysql 查看进程方式查看
    Mysql -uroot -p你的密码 进入mysql代表安装成功

  2. MySQL服务的启动停止重启操作
    Sudo service mysql start 开启服务
    Sudo service mysql stop 停止服务
    Sudo service mysql restart 重启服务

  3. 连接数据库和退出数据库(本机连接和外部访问连接)
    内部链接:自己玩自己
    外部链接:外部可玩我们的db: 以下是步奏:
    1、进入数据库 mysql –uroot –p你的密码
    2、Show databases 查看所有的数据库
    3、Use mysql 使用mysql数据库
    4、Show tables 查看mysql库中所有的表
    5、Select user,host from user; 在user 这个表里面查看用户和用户权限字段

7、grant all privileges on . to root@"%" identified by “123456” with grant option; 创建用户并且赋予权限
8、
Host: 是权限问题;
 % 允许自己玩,也允许别人人玩
Localhost 代表只能自己玩
*.*: 所有的库下的, 所有的表
identified by : 身份认证通过。。。。

10、delete from user where user=’root’ and host = ‘localhost’; 删除原来初始创建的root用户

11、flush privileges; 刷新数据库特权
Ps: 删除后,永远记得flush privileges

12、sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf[一定记住地址]
打开配置文件,将bind_address修改为0.0.0.0

13、重启mysql服务,必须:

14 经过上面的步奏,你的db就变成一个牛逼的db了,你也一样可以 使用windows下客户端进行连接,

上面步奏的重点回顾:
目标:为数据库创建新用户并且赋予权限允许外部链接
显示所有的数据库发现有一个mysql的数据库,
在这个数据库当中有一张user表专门记录数据库的用户,我们可以查看一下用户的账户和权限:
发现刚安装好的数据库有一个超级管理用户root并且权限是本机,我们可以新建一个新用户,并且允许所有外部用户连接。

grant all privileges on . to liuyuan@"%" identified by “123456” with grant option; 创建用户并且赋予权限

②、flush privileges;  刷新数据库特权  
③、修改配置文件, 重启mysql服务

6、数据库的图形界面操作
Navcat mysql

7、数据的逻辑删除和物理删除
逻辑删除本质上就是给表多加一个字段,用这个字段去标示删除和未删除的状态。
8、数据库命令行操作

3.对数据库的操作crd 共5个命令:
查看所有数据库 show databases;
查看当前数据库 select database();
切换数据库 use [数据库名];
创建数据库 create database [数据库名] charset=utf8;
删除数据库 drop database [数据库名];
Create database test1 charset=utf=8;
Show databases;
Use test1
Select database();
Drop database test1
数据库名字不可改, 会造成丢数据

4.对表的操作crud
查看所有表 show tables;
创建表 create table [表名](字段1 类型1 约束1,字段2 类型2 约束2);
删除表 drop table [表名]
修改表名字 rename table [表名] to [新名]

create table students(
id int primary key not null auto_increment,
name varchar(50) not null,
age int default 18,
gender bit,
birthday datetime,
is_delete bit default 0);
Show tables;
Rename table students to stu;
Show tables;
Drop table stu;

5.对字段的操作crud
查询字段(表结构) desc [表名]
增加字段 alter table [表名] add [字段名 类型 约束]
删除字段 alter table [表名] drop[字段名]
修改字段 alter table [表名] change [字段名] [新字段名 类型 约束]

Show tables;
Desc students;
Alter table students add weight decimal(5,2);
Desc students;
Alter table studnets change weight wei decimal(5,2);
Desc studnets;
Alter tables studnets drop wei;
Ps: 字段也是不可改, 虽然有此命令,但不建议用。

删除主键:需要先把主键的改为普通的id 不能是自动增长,然后再删除主键  , 一个表必须有一个主键,然后又设置回来。

① 、alter table students change id id int;
②、alter table students drop primary key;
③、alter table students change id id int auto_increment primary key not null;
6.对数据的操作
1.增加数据
插入一个全字段
insert into students values(0,’liuyuan’,31,1)
插入多个全字段
insert into students values(0,’liudehua’,24,0),(0,’yangmi’,31,0)
插入一个部分字段
insert into students(id,name) values(0,’zhaoliying’)
插入多个部分字段
insert into students(id,name) values(0,’liushishi’),(0,’linzhiling’)
2. 删除数据
删除某一条
delete from students where id=1;
清空
delete from students;
3. 修改数据
update student set name=’liuyuan’ where name=’liudehua’
4. 查找数据
查找所有数据
select * from students

insert into stu values(0,‘zhaoliying’,31,0,‘1987-09-09’,0);
解析:
0是id的占位, 不管哪一个必须写0来占,
名字: 字符串,
Birthday: 字符串
其它: 默认的也要写上值

Select * from stu;

温馨提示 : bit: 如果是0 , 不显示, 如果是1, 会显示2进制的形式
Desc stu;
insert into stu values(0,‘liudehua’,50,1,‘1989-07-07’,0);
Select * from stu;

合并起来, 一次插入多个:
insert into stu values(0,‘yangmi’,32,0,‘1989-09-09’,0),(0,‘liushishi’,30,0,‘1898-09-09’,0);
Select * from stu;

合并 插入必须字段;
insert into stu(id,name) values(0,‘lei’),(0,‘lili’);
Select * from stu;

update stu set gender=1 where name=‘lei’;
Select * from stu;

update stu set age=50,is_delete=1 where name=‘lili’;
Slect * from stu;

delete from stu where id=6;
Slect * from stu;
Delete from students; 清空表中所有数据。
Select * from stu;

9、数据库备份和恢复*****
备份: sudo mysqldump –uroot –proot test1 > ~/Desktop/test1back.sql
[]ps: mysqldump 数据库备份命令
Test1 数据库名字

重定向
.sql 格式: 因为是数据库

恢复:进入mysql先要创建一个新的数据库,注意字符集
	然后退出mysql
	sudo mysql –uroot –proot test1  < ~/Desktop/test1back.sql

第一步:备份
sudo mysqldump –uroot –proot test1 > ~/Desktop/test1back.sql

第二步:
Mysql -uroot -proot
Create database test2 charset=utf8;
Exit;

第三步:恢复
Sudo mysql -uroot -proot test2 < ~/Desktop/test1back.sql

查看成果:
Mysql -uroot -proot
Show tables;

作业:
创建一张学生信息表students:包含字段:id name age birthday is_delete
创建一张学科信息表subjects:包含字段:id name is_delete
分别使用图形界面和命令行对这两张表进行熟练的crud操作

数据库的操作一般查询和其它的操作比例:9:1
10、数据库查询
a.单表查询
1、查询单列数据
select name from students
2、查询所有列的数据
select * from students
3、去重查询单列
去重xxx只能显示去重的xxx的那一列
select distinct gender from students;

如果查去重所有的,没办法显示去重的效果,  因为id, name不能去重, 所以会全部显示。
select distinct * from  students

Select * fr0m stu;
Select name,age from stu;
select distinct age from students; ---->

4、条件查询where(图)
①、比较运算符
> < = >= <= !=
②、逻辑运算符(and or not)
例:
查询id大于3的学生
查询id不大于6的学生
查询姓名不是XXX的学生
查询没有删除的学生
查询id大于3的女生
查询id小于4或者没被删除的学生

③、模糊查询 like _和%
_: 下滑线代表任意的单个字符
%: 任意的0个或多个字符
Like: 模糊查找
Ps: 底层, _ 和 % 它们的效率是不同的。

例:
查询姓赵的学生
查询姓杨后面单名的学生
查询姓赵或者叫幂的学生

姓赵的
Select * from stu where name like ‘赵%’
2个字的:叫猴哥:
Select * from stu where name liek ‘猴_’
赵x颖
Slect * from stu where name like ‘赵_颖’
查询姓赵或者叫幂的学生
Slect * from stu where name like ‘赵%’ or name like ‘%幂’
Ps: 2个前面都加上name like
因为写条件的时候, and, or, not, 前面的条件要自成一体,后面的也要自成一 体哦!!!!

④、范围内查找:连续和不连续  between  in

例:
查询id是1或者3或者5的学生
查询id是2到6之间的学生
查询id是2到6之间的女生

⑤、空判断查找  is null     is not null
例:
	查询生日为空的学生
	查询生日不为空的学生
	查询生日为空的女生

5、聚合查询 对某一列数据进行统计
count(列名) 求某一列的总行数 count(*) |count(列名)
sum(数字列名) 求某一列的和
avg (数字列名) 求某一列的平均值
max (列名) 求某一列的最大值
min(列名) 求某一列的最小值
Ps: 上面都是对某一列的处理

Select sum(id) from stu;
Select avg(age) from stu;
Select count(name) from stu;

聚合出来的只会是一个值, 所以它不能与多值的一起出来;

6、分组 group by

Select count(*) from stu group by age;
Select max(age) from stu group by gender;
Select avg(age) from stu group by gender;

分组是为了更好的去做聚合而出现的,把列的值相同的归为一组
根据一个字段分组之后,无法看到别的字段信息 (只有分组的可见!!!!)
根据id 字段分组之后,可以查看到分组后其它的字段信息

	查询男女生的人数

Select count(*) from stu group by gender having gender = o;

分组条件筛选having(图)
	查询男生的人数   两种方法
group by 存在时,select中除了聚合函数外,所有的基本列必须是group by里面存在的;having基本上同group by一起使用的,having类似于where语句,只是having过滤是基于group by 分组后的数据,having一般通过select语句里面的聚合函数进行过滤。

Ps: groupby 与 where的区别

Select count() from stu where id>3 group by gender having gender =0;
Select count(
) from stu where id<6 group by age having age=30;

7、排序 order by [列1],[列2]
先按照列1去排序,默认是按照asc排序(正序 小——》大, 默认),如果要倒序,在后面加desc。
按照列1排序完成后,如果有顺序相同的,再按照列2进行排序。
Select *from students order by age desc,name asc;
Ps: 先按age desc(倒序),如果age有相同的, 综再按name的asc去排

7、限制集(分页) limit [start] , [count]

每页显示m条数据,当前显示第n页

求总页数:
查询总条数p1
使用p1除以m得到p2
如果整除则p2为总数页
如果不整除则p2+1为总页数

求第n页的数据
select * from students where isdelete=0 limit (n-1)*m,m[
开始数据的索引,向后取m条数据(1页)
limit [start] , [count]]

(关系表)操作:
9、关系表(多表)
关系: 1对1 1对多 多对多
AB表1对1 A ——》 B 1:1
B ——》 A 1:1

AB表1对多           A   ——》  B       1:1
		       B   ——》  A       1:多

AB表多对多           A    ——》B        1:多
		       B    ——》A         1:多
关系怎么表示:  关系字段(外键)
关系字段定义在哪个表:
关系字段约束(外键约束):  保证添的[]id 在有关系表的id范围内, 如果不在, 会直接报错,	不让加入。

关系字段定义在哪个表:

10、关系表的创建
先创建表和关系字段,再对关系字段添加约束(了解: 因为涉及到修改字段, 不建议)
alter table scores add constraint stu_score[这个名字无所谓, 但需要有就可以

后面加上 foreign key

] foreign key(stuid) references students(id);

创建表的时候创建关系字段和外键约束
mysql> create table scores(
-> id int auto_increment primary key not null,
-> score decimal(5,2),
-> stuid int,
-> subid int,
-> is_delete bit default 0,
-> foreign key(stuid) references students(id),
-> foreign key(subid) references subjects(id));

级联操作的类型包括:
使用方法:
foreign key(subid) references subjects(id)on delete cascade

restrict(限制):默认值,抛异常
cascade(级联):如果主表的记录删掉,则从表中相关联的记录都将被删除
set null:将外键设置为空
no action:什么都不做
上面这四种方案都不是最好的,最好的还是,推荐使用逻辑删除

11、关系表的查询
子查询
查询赵丽颖Python的分数
1、select id from students where name = ‘赵丽颖’
2、select id from subjects where name = ‘python’;
3、select score from scores where stuid = (select id from students where name = ‘赵丽颖’)and subid =(select id from subjects where name = ‘python’);

内连接
三种都行:
select students.name as 姓名,subjects.name as 科目,scores.score as 分数 from scores
inner join students on students.id = scores.stuid
inner join subjects on subjects.id = scores.subid;

select students.name as 姓名,subjects.name as 科目,scores.score as 分数 from students
inner join scores on scores.stuid = students.id
inner join subjects on scores.subid = subjects.id;

select students.name,subjects.name,scores.score from subjects
inner join scores on scores.subid = subjects.id [更大表 scores+subject]
inner join students on students.id = scores.stuid;[在上面的2表连接上, 再加入关系表studnets]

左连接
select students.name,scores.score from students
left join scores on students.id = scores.stuid;
Left join 是把left左边的表作为基准,显示所有的左边这张表的数据,如果left右边的表没有数据和左边表数据对应,全部以null替代

右连接
select students.name,scores.score from scores
-> right join students on students.id = scores.stuid;
Right join 是把right右边的表作为基准,显示所有的右边这张表的数据,如果right左边的表没有数据和右边表数据对应,全部以null替代

作业:
1、单表的所有
2、深刻理解关系表的关系
3、关系表的创建(重点掌握创建表带外键约束)
4、关系表的连接查询(了解子查询)
5、自己发掘实体1对多,练习上述操作!

(二)复习:
1 select * 永远是在最后
开始: where id > 3 (and、or,not) name like ‘zhao%’
Where id in(2,3,5)
Where id between 2 and 9;
select distinct gender from students;
先有聚合, 再有select count(*) from stu where id >3 group by gender having gender=0
Select * from stu Order by age desc, name asc
Select * from stu where is_delete=0 limit (n-1)*m, m

分数表认识 赵丽颖,
以后用的都是多对1 (因为多对多, 全转化为一对多), 关系 全放于多的表中,
创建表的同时, 直接也写上外键约束
左、右、内连接
视图

1、前一天回顾
a)单表的查询
基本:(去重distinct)
条件:比较、 逻辑 、模糊、范围、空判断
聚合:sum max min avg count
分组:分组的特点*****
Select gender,sum(age) from students group by gender;
这样是可以的,不可以单独选择age,但是可以对其它字段聚合
Having
排序: 正序asc 小-大 默认
倒序desc
限制:开始索引 数量 limit start number

b)关系表(关联表)的创建和查询
关系是什么(关系字段)
关系怎么去表示(引用主键)
关系字段的约束(外键约束)
关系表的查询(子查询,连接查询)

习题分析(连接查询)
查询男生的姓名以及每个人的总分
姓名和总分 ----》 students和scores
男生 是条件
Name 是分组的条件
查询科目的名称以及平均分
科目的名称 平均分 — subjects scores
分组的条件 科目的名称subjects.title
查询未删除的科目的名称,平均分,最高分
科目的名称 平均分 最高分 subjects scores
未删除是条件
分组的条件 subjects.title
2、自关联 省–市--区
什么是自关联
一张表自己和自己关联
为什么要自关联,怎么做
如果不自关联
第一特点:字段固定有限
第二个特点:省市区1对多关系
第三个特点:存储的数据量是少数的有限条
但是,数据库创建表是有消耗的,如果按照不自关联的思想去做,要创建3张表,都存储少量的数据,造成大量的浪费。因此,我们就需要想办法让三张表合一,形成自关联。

如何创建自关联表
mysql> create table areas(
-> id int primary key not null auto_increment,
-> name varchar(50) not null,
-> pid int,
-> foreign key(pid) references areas(id));

导入外部表数据

1、先把外部表sql文件拖到桌面上
2、在桌面上重新进入mysql
3、在选择的数据库当中新建表,表名和sql文件名字一致
create table areas(
id int primary key auto_increment not null,
name varchar(30),
pid int, foreign key(pid) references areas(id));
Use xxx(数据库名字)
Source areas.sql
4、在mysql中输入命令:source 文件名.sql

自关联表的查询
查询所有的省
Select *from areas where pid is null;
查询某个省的所有市还有区县
查询某个省的所有市/查询某个市的所有区县
3、视图 view
1)什么是视图:
本质上就是对sql查询语句的封装
为什么要使用视图
对于复杂的查询语句维护起来不方便
从不同的角度有不同的数据形式
2)视图的特性
视图本身并没有确切的数据,它的数据来源于定义查询语句时候的基本表。
(*****当基本表数据发生改变的时候,调用视图所得的结果也会改变)
4、怎么玩
查看视图 show tables;
创建视图 create view [视图名字] as [查询语句 ]
查询语句比较麻烦,先封装一个视图
create view v_sheng as select sheng.name as 省,shi.name as 市,qu.name as 区县 from areas as sheng inner join areas as shi on shi.pid = sheng.id
inner join areas as qu on qu.pid = shi.id;
再根据创建的视图查询各个省的信息
Select * from v_sheng where 省 = ‘某某省’
修改视图 alter view [视图名字] as [查询语句]
修改视图的名字:rename table [旧名] to [新名]
删除视图 drop view [视图名字]

5、索引(双刃剑)
本质是一种算法,当数据量越来越大的时候需要优化查询
单列索引和组合索引
查看索引 show index from areas
创建索引 create index [indexname] on areas(atitle)
删除索引 drop index [indexname] on [tablename]
修改索引: 先删除再添加
查看添加索引后的效率
1)Set profiling = 1 开启运行时间检测
2)在大数据量表中查询有关信息
3) show profiles; 查看时间

6、事务(mysql innodb引擎支持 事务 )
a)Myisam innodb引擎区别
InnoDB支持事务,而MyISAM不支持事务
InnoDB支持行级锁,而MyISAM支持表级锁
InnoDB支持MVCC, 而MyISAM不支持
InnoDB支持外键,而MyISAM不支持
InnoDB不支持全文索引,而MyISAM支持。

Show engines 查看数据库的引擎
Show create table students 查看创建表的过程里面可以看到引擎版本

    事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序。

使用事务可以保证一个复杂业务逻辑的完整性和正确性
事务的操作:
1、开启事务 begin
2、执行业务逻辑sql
3、选择提交或者回退 commit | rollback
7、数据库与Python进行交互
a) Python当中可以与数据库进行交互,但是要想去连接数据库需要安装对应版本的驱动包,Python2要安装MySQLdb,Python3需要安装PyMysql,使用方式基本一致
b) 驱动包的安装 pip3 install pymysql
如果没有安装pip3,先进行安装pip3 sudo apt-get install python3-pip
c) 使用方法:参考第四章文档
①、单独实现增删改查脚本
查询:3种方式 (查1个 查多个 查所有)
Connect 对象的作用
Commit()
Close()
Cursor 对象
Scroll
Fetchone
Fetchall
Fetchmany
Close()
sql注入
防止sql注入 参数化(params列表)

②、将增删改查实现封装函数
③、将增删改查实现封装为类
④、使用封装好的工具类进行测试

8、查底层创建表的细节: show create table students;

可以看到表的创建的字段的细节, 及用的引擎是innoDB, 以及编码是哪个
上面我建库的时候, 编码没有写 charset=’utf8’ 结果造成了系统默认的了, 不认识中文它, 我也是醉了。

同样的, 也有查db的创建: show create database stu

9 cur如何查:
游标当前的位置, 与 cur.fectchall(), fetchone(), fetchmany(3), cur.scroll(-2)[
def fetchone(self):
“”“Fetch the next row”""
def fetchmany(self, size=None):
“”“Fetch several rows”""
def fetchall(self):
“”“Fetch all the rows”""
def scroll(self, value, mode=‘relative’):] 来完成查的功能
下面是例子:
from pymysql import connect

def main():[表中的原始数据:
±—±----------±-----±----------+
| id | name | age | is_delete |
| 1 | 傻逼 | 30 | |
| 2 | 组长 | 30 | |
| 3 | 丽丽 | 30 | |
| 4 | 王航 | 30 | |
| 5 | 孙伟达 | 30 | |
±—±----------±-----±----------+]
conn = connect(host=‘192.168.11.93’,port=3306,user=‘root’,password=‘root’,db=‘test2’,charset=‘utf8’)
cur=conn.cursor()
sql=‘select * from stu’
cur.execute(sql)
a=cur.fetchone()
a=cur.fetchall()
[
((2, ‘组长’, 30, b’\x00’), (3, ‘丽丽’, 30, b’\x00’), (4, ‘王航’, 30, b’\x00’), (5, ‘孙伟达’, 30, b’\x00’))
] print(a)

if name == ‘main’:
main()

a=cur.fetchone()
[

(1, ‘傻逼’, 30, b’\x00’)]
第三种取法:
a =cur.fetchone()
a = cur.fetchone()[
(2, ‘组长’, 30, b’\x00’)]

第三种取法:
a=cur.fetchone()
cur.scroll(-1)
a = cur.fetchone()[
(1, ‘傻逼’, 30, b’\x00’)]

第四种取法:

a = cur.fetchmany(3) [
((1, ‘傻逼’, 30, b’\x00’), (2, ‘组长’, 30, b’\x00’), (3, ‘丽丽’, 30, b’\x00’))]

第五种取法:
a=cur.fetchall()
a=cur.fetchone()[
None]

10例子注释(pymysql connct)
def main():
#第一步创建连接对象
conn = connect(host=‘192.168.11.93’,port=3306,user=‘root’,password=‘root’,db=‘test2’,charset=‘utf8’)
#第二步创建游标对象
cur = conn.cursor()
#构造sql语句
sql = ‘select * from stu’
#使用游标对象执行sql语句
cur.execute(sql)
#通过游标对象可以查看查询的结果
#返回的是所有数据,每个数据是一个小元组,然后全部放在一个大元组当中
# a = cur.fetchall()
# 返回的是一个数据,这个数据用元组封装
a = cur.fetchone()
cur.scroll(1)
# a = cur.fetchall()
a = cur.fetchmany(3)
print(a)

cur.close()
conn.close()

11 封装成类:
from pymysql import connect

class MysqlHandler(object):
def init(self,host,port,user, password, db,charset):
self.host=host
self.port=port
self.user=user
self.password=password
self.db=db
self.conn=None
self.cur=None
[] self.charset=charset

def open(self,sql):
    self.conn = connect(host=self.host,port=self.port,user=self.user,
                        password=self.password,db=self.db,charset=self.charset)
    self.cur = self.conn.cursor()
    self.cur.execute(sql)

def close(self):
    self.cur.close()
    self.conn.close()

def cud(self):
    self.conn.commit()

[] self.close()

def read(self):
    a=self.cur.fetchall()
    self.close()
    return a

if name == ‘main’:
sqlhe = MysqlHandler(host=‘192.168.11.93’,port=3306,user=‘root’,password=‘root’,db=‘test2’,charset=‘utf8’)
sqlhe.open(‘delete from stu where id in(2,5)’)
sqlhe.cud()
print(‘ok’)

一、Mysql 的查询全表

二、MySQL的JOIN(一):用法
2张表的连接
JOIN的含义就如英文单词“join”一样,连接两张表,大致分为内连接,外连接,右连接,左连接,自然连接。这里描述先甩出一张用烂了的图,然后插入测试数据。

① 3张表的连接, 5张, 10张表的连接:
本质上都是2张表的连接的基础上 过来的, 所以不管多少张表, 连接的方式画出来都是上面的7种样子

② 表连接:的代码实现
(一)笛卡尔积:CROSS JOIN
要理解各种JOIN首先要理解笛卡尔积。笛卡尔积就是将A表的每一条记录与B表的每一条记录强行拼在一起。所以,如果A表有n条记录,B表有m条记录,笛卡尔积产生的结果就会产生n*m条记录。下面的例子,t_blog有10条记录,t_type有5条记录,所有他们俩的笛卡尔积有50条记录。有五种产生
SELECT FROM t_blog,t_type; 笛卡尔积

Select inner join

Need to write

左连接:LEFT JOIN
SELECT * FROM t_blog INNER JOIN t_type ON t_blog.typeId =t_type.id;

SELECT * FROM t_blog LEFT JOIN t_type ON t_blog.typeId=t_type.id;

SELECT * FROM t_blog RIGHT JOIN t_type ON t_blog.typeId=t_type.id;

SELECT * FROM t_blog LEFT JOIN t_type ON t_blog.typeId=t_type.id
UNION

SELECT * FROM t_blog RIGHT JOIN t_type ON t_blog.typeId=t_type.id;

SELECT * FROM t_blog LEFT JOIN t_type ON t_blog.typeId=t_type.id
WHERE t_type.id IS NULL
UNION
SELECT * FROM t_blog RIGHT JOIN t_type ON t_blog.typeId=t_type.id
WHERE t_blog.id IS NULL;

另外MySQL不支持OUTER JOIN,但是我们可以对左连接和右连接的结果做UNION操作来实现。

三、MySQL的JOIN(二):JOIN原理
http://www.cnblogs.com/fudashi/p/7506877.html
(一)表连接算法
Nested Loop Join(NLJ)算法:

首先介绍一种基础算法:NLJ,嵌套循环算法。循环外层是驱动表,循坏内层是被驱动表。驱动表会驱动被驱动表进行连接操作。首先驱动表找到第一条记录,然后从头扫描被驱动表,逐一查找与驱动表第一条记录匹配的记录然后连接起来形成结果表中的一条记。被驱动表查找完后,再从驱动表中取出第二个记录,然后从头扫描被驱动表,逐一查找与驱动表第二条记录匹配的记录,连接起来形成结果表中的一条记录。重复上述操作,直到驱动表的全部记录都处理完毕为止。这就是嵌套循环连接算法的基本思想,伪代码如下。
foreach row1 from t1
foreach row2 from t2
if row2 match row1 //row2与row1匹配,满足连接条件
join row1 and row2 into result //连接row1和row2加入结果集

首先加载t1,然后从t1中取出第一条记录,之后加载t2表,与t2表中的记录逐个匹配,连接匹配的记录。
Block Nested Loop Join(BNLJ)算法:
再介绍一种高级算法:BNLJ,块嵌套循环算法,可以看作对NLJ的优化。大致思想就是建立一个缓存区,一次从驱动表中取多条记录,然后扫描被驱动表,被驱动表的每一条记录都尝试与缓冲区中的多条记录匹配,如果匹配则连接并加入结果集。缓冲区越大,驱动表一次取出的记录就越多。这个算法的优化思路就是减少内循环的次数从而提高表连接效率。
(二)影响性能的因素

1.内循环的次数:现在考虑这么一个场景,当t1有100条记录,t2有10000条记录。那么,t1驱动t2与t2驱动t1,他们之间在效率上孰优孰劣?如果是单纯的分析指令执行次数,他们都是100*10000,但是考虑到加载表的次数呢。首先分析t1驱动t2,t1表加载1次,t2表需要加载100次。然后分析t2驱动t1,t2表首先加载1次,但是t1表要加载10000次。所以,t1驱动t2的效率要优于t2驱动t1的效率。由此得出,小表驱动大表能够减少内循环的次数从而提高连接效率。
另外,如果使用Block Nested Loop Join算法的话,通过扩大一次缓存区的大小也能减小内循环的次数。由此又可得,设置合理的缓冲区大小能够提高连接效率
2.快速匹配:扫描被驱动表寻找合适的记录可以看做一个查询操作,如何提高查询的效率呢?建索引啊!由此还可得出,在被驱动表建立索引能够提高连接效率
3.排序:假设t1表驱动t2表进行连接操作,连接条件是t1.id=t2.id,而且要求查询结果对id排序。现在有两种选择,方式一[…ORDER BY t1.id],方式二[…ORDER BY t2.id]。如果我们使用方式一的话,可以先对t1进行排序然后执行表连接算法,如果我们使用方式二的话,只能在执行表连接算法后,对结果集进行排序(Using temporary),效率自然低下。由此最后可得出,优先选择驱动表的属性进行排序能够提高连接效率。
Ps:谨记一句,小表驱动大表可以减小内循环的次数
(三)内连接谁当驱动表
实际业务场景中,左连接、右连接可以根据业务需求认定谁是驱动表,谁是被驱动表。
但是内连接不同,根据嵌套循环算法的思想,t1内连接t2和t2内连接t1所得结果集是相同的。那么到底是谁连接谁呢?谨记一句话即可,小表驱动大表可以减小内循环的次数。下面用 STRAIGHT_JOIN强制左表连接右表。By the way,STRIGHT_JOIN比较冷门,在这里解释下,其作用相当于内连接,不过强制规定了左表驱动右边。详情看这MySQL的JOIN(一):用法

1.内连接的最佳实践:直接让MySQL去判断
但是,表的记录数是会变化的,有没有一劳永逸的写法?当然有啦,MySQL自带的Optimizer会优化内连接,优化策略就是上面讲的小表驱动大表。所以,以后写内连接不要纠结谁内连接谁了,直接让MySQL去判断吧。

EXPLAIN SELECT * FROM t1 INNER JOIN t2 ON t1.type=t2.type;
EXPLAIN SELECT * FROM t2 INNER JOIN t1 ON t1.type=t2.type;
EXPLAIN SELECT * FROM t1 JOIN t2 ON t1.type=t2.type;
EXPLAIN SELECT * FROM t2 JOIN t1 ON t1.type=t2.type;
EXPLAIN SELECT * FROM t1,t2 WHERE t1.type=t2.type;
EXPLAIN SELECT * FROM t2,t1 WHERE t1.type=t2.type;

上面6条内连接SQL,MySQL的Optimizer都会进行优化。

四、MySQL的JOIN(四):JOIN优化实践之快速匹配
https://www.cnblogs.com/fudashi/p/7521915.html

这篇博文讲述如何优化扫描速度。我们通过MySQL的JOIN(二):JOIN原理得知了两张表的JOIN操作就是不断从驱动表中取出记录,然后查找出被驱动表中与之匹配的记录并连接。这个过程的实质就是查询操作,想要优化查询操作,建索引是最常用的方式。那索引怎么建呢?我们来讨论下,首先插入测试数据。
– 首先两个表都没建索引
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.type=t2.type;

(一)内连接
我们知道,MySQL Optimizer会对内连接做优化,不管谁内连接谁,都是用小表驱动大表,所以如果要优化内连接,可以在大表上建立索引,以提高连接性能。
另外注意一点,在小表上建立索引时,MySQL Optimizer会认为用大表驱动小表效率更快,转而用大表驱动小表。
对内连接小表驱动大表的优化策略不清楚的话,可以看MySQL的JOIN(三):JOIN优化实践之内循环的次数

(二)三表连接
上面都是两表连接,三表连接也是一样的,找出驱动表和被驱动表,在被驱动表上建立索引,即可提高连接性能。
(三)总结
想要从快速匹配的角度优化JOIN,首先就是找出谁是驱动表,谁是被驱动表,然后在被驱动表上建立索引即可。

左、右,内连接的3种加索引的例子 见连接:
https://www.cnblogs.com/fudashi/p/7521915.html

左右是一种放一起
内连接是另 一种例子哦, MySQL Optimizer会对内连接做优化,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值