mysql

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 数据库的增删改查

@[TOC](目录)

##    数据库基本操作


```

创建用户:

       create user 'khw'@'192.168.1.1' identified by '123123'

       create user 'khw'@'%' identified by '123123';

       # %号匹配所有

授权:

       创建权限

       grant select,insert,update   on db1.* to 'khw'@'%'

       grant all privileges on  mysql.* to 'khw'@'%'

       privileges:(表示拥有所有权限)

       db1.*:(表示这个数据库里面的所有表)

       to 'khw'@'%':表示把这个权限给khw这个用户


查看:

       use mysql;

       select user,host from user #查看user这个表里的user,host两列

 

设置密码:

       mysqladmin -uroot -p 原密码 password 新密码

       该命令在终端输入即可,无须进入客户端

     

破解密码:

       可以将mysql获取用户名和密码校验的功能看出一个装饰器

       装饰在了客户端请求访问的功能上,将装饰器溢出就可以不校验用户名密码了

       1、先关闭当前mysql服务端

           #命令行的方式启动(让mysql跳过用户密码验证功能)

           mysql --skip-grant-tables;

       2、直接以无密码的方式连接

           mysql -uroot -p;

       3、修改当前用户的密码

           update mysql.user set password=password(123456) where user='root' and host='localhost';

           """真正存储用户表的密码字段,肯定是密文"""

       4、立刻将修改数据刷到硬盘

           flush privileges;

```


## 库的增删改


```

增:

   create database db2 default charset=utf8; 创建数据库

查:

   show databases; 查看数据库

   show create database db1;  查看单个

删:

   drop database db2; 删除数据库

改:

   alter database db2 charset='utf-8'; 修改

```


## 表的增删改


```

查看当前所在库的名字

   select database();


进入数据库:

   use db2;


增:

   create table t1(id int,name char(10)) default charset=utf8;  

       # 创建表第一列名称为id int类型,第二列名称为name char类型,最多存10个字符


查:

   show tables;  # 查看当前库下面的所有表名

   show create table t1;  # 查看单一表

   describe t1;  # 支持简写 desc t1;


改:

   alter table t1 modify name char(16); # 将char的最大字符改为16


删:

   drop table t1;



     

     


```


## 操作表中的内容


```

查:

   select * from t1;

   select name from t1; # 查name这一列的数据


增:

   insert into t1 values(1,'jason');

   insert into t1 values(1,'jason'),(2,'egon'),(3,'tank');

 


改:

   update t1 set age=18   # set表示设置,将age这一列都改为18

   update t1 set age=18 where age=17  # 将age这一列里17改为18,where为限制条件

 

   delete from t1 where id>6 # 将t1这张表里id大于6的都删掉

delete from t1 where name='json'


将表所有的数据清空:

delete from t1;

```


## 创建表的完整语法


```

# 语法

create table 表名(

字段名1 类型(宽度) 约束条件,

   字段名2 类型(宽度) 约束条件,

   字段名3 类型(宽度) 约束条件,

)



# 注意

1、在同一张表中字段名不能重复

2、宽度和约束条件是可选的,而字段名和类型是必选的

3、约束条件可以支持写多个

create table t1(

    字段名1 类型(宽度) 约束条件1 约束条件2 ....

   )

 

4、最后一行不能有逗号

create table t1(

    id int,

       name char, # 报错

   );

 

 

"""补充"""

# 宽度

一半情况下指的是对存储数据的限制

   create table t1(name char); 默认宽度是1

   insert into t1 values('jason')  # 应为宽度唯一,所以这次插入只能插进j

   insert into t1 values(null);  # 关键字NULL,插入关键字null

 

# 约束条件 null , not null

create table t1(id int, name char not null)  #不能插入null


 

# 宽度和约束条件的关系

宽度是来限制数据的存储

   约束条件是在宽度的基础之上增加额外的约束

 


```


## 修改表


```

# MySQL 对大小写是不敏感的

"""

1、修改表名

alter table 表名 rename 新表明;


2、增加字段

alter table 表明 add 字段名 字段类型(宽度) 约束条件;  默认是在尾部

alter table 表明 add 字段名 字段类型(宽度) 约束条件 first; 将字段添加到表的最前面

alter table 表明 add 字段名 字段类型(宽度) 约束条件 after 字段名;  更在谁的后面


3、删除字段

alter table 表名 drop 字段名;


4、修改字段

alter table 表名 modify 字段名 字段类型(宽度) 约束条件;

alter table 表名 change 旧字段名 新字段名(宽度) 约束条件;


"""

```


## 复制表(了解)


```

# sql语句的结果其实也是一张虚拟表

"""

create table 新表名 select * from 旧表;  不能复制主键 外键

"""

```




## Mysql主要存储引擎


```

日常生活中文件格式有很多,并且针对不同的文件格式有对应不同存储方式和处理机制

针对不同的数据应该有对应不同的处理机制来存储

存储引擎就是不同的处理机制


innodb:

是Mysql5.5版本之后默认的存储引擎

存储数据更加的安全

   # 文件个数两个,frm 表结构,ibd 表数据

myisam:

是Mysql5.5版本之前默认存储引擎

速度要比innodb更快 但我们更加注重的是数据的安全

   # 文件个数三个,frm 表结构,myd 表数据, Myl 索引

memory:

内存引擎,数据放在内存中,断电丢失

   # 文件个数一个,frm 表结构,数据都在内存追踪

blackhole:

无论存什么,都立刻消失

   # 文件个数一个,frm 表结构


"""

# 查看所有的存储引擎

show engines;


"""


```


## 基本数据类型


```

整形

1、分类:

    tinyint smallint meduimint int gifint

   2、作用:

    存储年龄、等级、id、号码等等

3、详细介绍: 图片链接

"""

# 针对整型 括号内的宽度有啥用

只有整型括号里的数字不是表示限制位数

id int(8)

如果数字没有超出8魏,默认用空格填充至8位

如果数字超出了8位,有几位存几位(但还是要遵守最大范围)


总结:

针对整型字段 括号内无须指定宽度,应为他的默认宽度足够存常见数据了


"""


浮点型

1、分类

    FLOAT、DOUBLE、DECIMAL

   2、作用

    身高、体重、薪资

3、存储限制

    float(255,30) # 总共255位,小数部分30位

       double(255,30) # 总共255位,小数部分30位

       decimal(65,30) # 总共65位,小数部分30位

4、精确度

    float < double < decimal

     

     

事件类型

1、分类

    date 年月日

       datetime 年月日 时分秒

       time 时分秒

       year 年份

     

     

枚举与集合类型

1、分类

    枚举(enum) 多选一

       集合(set)  多选多

   2、作用:

       """

       create table user(

           id int,

           name char(16),

           gender enum('male','female')

       );

       insert into user values(1,'jason','male'); 正常

       insert into user values(2,'egon','xo'); 报错

       # 枚举字段 后期在存储数据的时候只能从枚举里面选择一个存储

       """

     

       """

       create table user(

           id int,

           name char(16),

           gender enum('male','female')

           hobby set('read','dbj','hecha')

       );

       insert into teacher values(1,'jason','read'); 正常

       insert into teacher values(2,'egon','female','dbj,hecha'); 正常

       insert into teacher values(3,'tank','others','生蚝');  报错

       # 结合可以只写一个或多个,但是不能写没有列举的

     

       """

 

```


#### 严格模式


```

# 如何查看严格模式

show variabels like "%mode"

模糊匹配/查询

关键字 like

    %:匹配任意多个字符

       -:匹配任意单个字符

     

# 修改严格模式

set session 只在当前窗口有效

   set global 全局有效

   set global sql_mode = "STRICT_TRANS_TABLES";

   修改完之后重新进入服务端即可

 


```


## 约束条件


### default 默认值


```

default 默认值

       # 补充知识点 插入数据的时候可以指定字段

       create table t1(

           id int,

           name char(16)

       );

       insert into t1(name,id) values('jason',1);


       create table t2(

           id int,

           name char(16),

           gender enum('male','female','others') default 'male'

       );

     

       # default 表示不填默认位male

       insert into t2(id,name) values(1,'jason');

       insert into t2 values(2,'egon','female');

 


     

```


### unique唯一


```

unique唯一

       # 单列唯一,一般位于id这一列

       create table t3(

           id int unique,

           name char(16)

       );

       insert into t3 values(1,'jason'),(1,'egon');

       insert into t3 values(1,'jason'),(2,'egon')

     

       # 联合唯一,例如ip和端口,单个可以重复,但是加载一起必须是唯一的

       create table t4(

           id int unique,

           ip char(16)

           port int,

           unique(ip,port)

       );

       insert into t4 values(1,'127.0.0.1',8080);

       insert into t4 values(2,'127.0.0.1',8080);

       insert into t4 values(2,'127.0.0.1',8080); #这条报错

```




### primary key主键


```

primary key主键

# 1、从约束效果上看 primary key 等价于not null+unique,非空且唯一

       create table t5(id int primary key);

       intsert into t5 values(null);   报错

       intsert into t5 values(1),(1);  报错

       intsert into t5 values(1),(2);

# 2、他除了有约束效果之外,他还是innodb存储引擎组织数据的依据,innodb存储引擎在创建表的时候必须要有primary key,应为他类似与书的目录 能够帮助提示查询效率 并且也是建表的依据

       """

       1、一张表中有且只有一个主键 如果没有设置主键,会从上往下搜索,知道遇到一个非空且唯一的字段 将他自动升级为主键

       create table t6(

           id int ,

           name char(16),

           age int not null unique,

           addr char(32) not null unique

       );

       2、如果表中没有主键也没有其他非空唯一字段 南无innodb会采用自己内部提供的一个隐藏字段为主键,隐藏意味着你无法使用,无法提升查询速度


       3、一张表中通常由一个主键字段,并且通常将id/uid/sid字段作为主键

       单个字段主键

       create table t5(

           id int primary key,

           name char(16)

       );

       联合主键(多个字段联合起来作为表的主键,本质还是一个主键)

       create table t4(

           id int unique,

           ip char(16)

           port int,

           primary key(ip,port)

       );

       """

所以我们在创建表的时候id字段一定要加primary key

```


### auto_increment自增


```

# 当编号太多,人为维护麻烦,可以使用此主键

create table t8(

id int primary key auto_increment, #id字段可以自增,并且非空且唯一

   name char(16)

)

insert into t8(name) values('json'),('egon'),('kevin');



总结:

以后再创建表的id(数据的唯一标识id、uid、sid)字段的时候

   id int primary key auto_increment

补充:

delete from 再删除表中数据的时候,主键的自增不会停止

   truncate t1 清空表数据并重置主键

```




## 表与表之间建关系


### 外键


```

外键是用来帮助我们建立表与表之间的关系

foreign key

```


### 一对多关系


```

"""

员工表与部门表为例

一个员工能否对应多个部门

 不能

一个部门能否对应多个员工

 能

得出结论

 员工表与部门表 是单向的一对多

 所以表关系就是一对多

"""

     

foreign key

1、一对多表关系,外键字段写在多的一方

   2、再创建表的时候,一定要先建被关联表

   3、再录入数据的时候,也必须先录入被关联表

     


# 部门表

create table dep(

id int primary key auto_increment,

   dep_name char(16),

   dep_desc char(32)

);

# 员工表

create table emp(

id int primary key auto_increment,

   name char(16),

   gender enum('male','female','oyhers') default 'male',

   dep_id int,

   foreign key(dep_id) references dep(id)

)


insert into dep(dep_name,dep_desc) values('sb教学部','教书育人'),values('外交部','人多外交');

insert into emp(name,dep_id) values('jason',2),values('egon',1);


# 级联操作:

   # 1、修改dep表里面的id字段

   update dep set id=200 where id=2;  不行

   # 2、删除dep表里面的数据

   delete from dep; 不行

   # 3、删除教学部门对应的员工数据,之后再删除部门

       操作繁琐

   # 4、真正做到数据之间的关系

       更新就同步跟新,级联更新

       删除就同步删除,级联删除

 

create table emp(

id int primary key auto_increment,

   name char(16),

   gender enum('male','female','oyhers') default 'male',

   dep_id int,

   foreign key(dep_id) references dep(id),

   on update cascade, # 同步更新

   on delete cascade # 同步删除

 

)

insert into dep(dep_name,dep_desc) values('sb教学部','教书育人'),values('外交部','人多外交');

insert into emp(name,dep_id) values('jason',2),values('egon',1);

```


### 多对多关系


```

"""

图书表和作者表为例

一本书可以对应多个作者

 可以

一个作者对应多本书

 可以

所以推出为多对多关系

两张表都有外键字段

"""

create table book(

id int primary key auto_increment,

   title varchar(32),

   price int,

   author_id int,

   foreign key(author_id) references author(id),

   on update cascade, # 同步更新

   on delete cascade # 同步删除

);


create table author(

id int primary key auto_increment,

   name varchar(32),

   age int,

   book_id int,

   foreign key(book_id) references book(id),

   on update cascade, # 同步更新

   on delete cascade # 同步删除

);

"""

foreign key

1、一对多表关系,外键字段写在多的一方

   2、再创建表的时候,一定要先建被关联表

   3、再录入数据的时候,也必须先录入被关联表

按照上述的方式创建一个都别想成功

其实我们只是想记录书籍和作者的关系

针对多对多字段表关系,不能在两张表原有的表中创建外键

需专门建立一张表,来存放外键

"""

create table book(

id int primary key auto_increment,

   title varchar(32),

   price int

);


create table author(

id int primary key auto_increment,

   name varchar(32),

   age int

);

create table book2author(

id int primary key auto_increment,

   author_id int,

   book_id int,

   foreign key(author_id) references author(id),

   on update cascade, # 同步更新

   on delete cascade, # 同步删除

   foreign key(book_id) references book(id),

   on update cascade, # 同步更新

   on delete cascade # 同步删除

);

```


### 一对一


```

"""

id name age addr phone hobby .....

如果一个表的字段特别多,每次查询又不是所有字段都能用得到

将表一分为二

用户表

 id name age

用户详情表

 id addr phone bobby email...

       站在用户表

           一个用户能否对应多个用户详情 不能

       站在详情表

           一个详情能否属于多个用户 不能

       结论:这种就属于一对一或者没有关系

"""

一对一外键字段建在任意一方都可以,但建议建在查询频率较高的表中

create table authordetail(

id int primary key auth_increment,

   phone int,

   addr varchar()

);

create table author(

id int primary key auth_increment,

   name varchar(32)

   age int,

   authordetail_id int unique,

   foreign key(authordetail_id) referemces aithordetail(id),

   on update cascade, # 同步更新

   on delete cascade # 同步删除

);

```


### 总结


```

"""

表关系建立需要用到 foreign key

一对多

 外键字段建在多的一方

多对多

 自己开设第三方存储

一对一

 建在任意一方都可以 但是推荐建在查询频率较高的表中

判断表之间关系的方式

换位思考!

 员工与部门

 图书与作者

 作者与作者详情

"""

```


## 查询表


### 前期表准备


```


"""

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

);


# 插入记录

# 三个部门 教学,销售,运营

insert into

emp(name,sex,age,hire_Date,post,salary,office,depart_id) values

('jason','male',78,'20150302','张江第一帅形象代言',7300,22,421,1), #以下是教学部

('top','male',28,'20150302','teacher',100000,33,421,1),

('owem','male',38,'20050302','teacher',8300,13,421,1),

('top','male',48,'20150302','teacher',9500,63,421,1),

('哈哈','male',58,'20150302','sale',6500,53,421,1), #以下是销售部

('呵呵','male',68,'20150302','sale',5500,63,421,1),

('憎龙','male',78,'20150302','sale',4500,73,421,1), #以下是运营部

('程咬铁','male',88,'20150302','sale',3500,93,421,1);

"""



```


### 几个重要关键字的执行顺序


```

# 书写顺序

select id,name from emp where id > 3;


#执行顺序

from

where

select


"""

可以按照书写顺序的方式写sql

select * 先用*占位

之后补全后面的sql语句

最后将*号替换成想要的字段

"""


```


### where筛选条件


```

# 作用:是对整体数据的一个筛选操作

1、查询id大于等于3小于等于6的数据

select id,name,age from emp where id>=3 and id<=6;

select id,nam,age from emp where id betwenn 3 and 6; 两者等价


2、查询薪资是20000或者18000或者17000的数据

slect * from emp where salary=2000 or salary=18000 or salary=17000;

select * from emp where salary in (2000,18000,17000);


3、查询员工姓名中包含字母o的员工姓名和薪资

"""

模糊查询

like

 %匹配任意多个字符

 _匹配任意单个字符

"""

select name,salary from emp where name like '%o%';


4、查询员工姓名是由四个字符组成的姓名和薪资

select name,salary from emp where name like '____';

select name,salary from emp where char_length(name) = 4;


5、查询id小于3或者大于5的

select * from emp where id not between 3 and 6


6、查询薪资不在20000,18000,17000范围的数据

select * from emp where salary not int (20000,18000,17000);


7、查询岗位描述为空的员工和岗位名,针对null 不用等号用is

select name,post from emp where post_comment = NULL;

select name,post from emp where post_comment is NULL;

```


### group by 分组


```

场景:

男女比例

部门平均薪资

部门秃头率

国家之间数据统计


分组语法:

select * from emp group by post;


 

聚合函数:

max

   avg

   sum

   count

 

ps: 分组之后,最小可操作单位是组,而不是单个数据,上述命令在非严格模式下可以执行,返回的是分组之后每个组的第一条数据 ,但这个不符合分组规范,分组之后不应该考虑单个数据,而应该以组为操作单位(分组之后 没办法直接获取组内的单个数据)

严格模式: set global sql_mode = 'strict_trans_tables,only_full_group_by';


 

1、获取每个部门的最高薪资

   select post,max(salary) from emp group by post;

   select post as '部门',max(salary) as '最高薪资' from emp group by post;

   ps: as可以给字段起别名


2、获取每个部门的最低薪资

select post,min(salary) from emp group by post;

 

3、获取每个部门的最高薪资

select post,avg(salary) from emp group by post;

 

4、获取每个部门的薪资综合

select post,sum(salary) from emp group by post;

 

5、获取每个部门的人数

select post,count(id) from emp group by post; # 常用

   select post,count(salary) from emp group by post;

   select post,count(age) from emp group by post;

select post,count(post_comment) from emp group by post;  # null不行


6、查询分组之后的部门名称和每个部门下所有的员工姓名

# group_concat 不单单可以支持你获取分组之后的其他字段,还支持拼接操作

select  post,group_concat(name) from emp group by post;

   select  post,group_concat(name,'_DSB') from emp group by post;

   select  post,group_concat(name,':',salary) from emp group by post;

   # concat 不分组的时候使用

   select concat('NAME:',name),concat('SAL:',salary) from emp;

 

7、查询每个人的年薪 12薪

select name,salary*12 from emp;

 

 

 

补充: as语法不仅能给字段起别名,还可以给表零时起别名

   select emp.id,emp.id from emp ;

   select emp.id,emp.id from emp as t1; 报错

   select t1.id,t1.id from emp as t1;

 

```


### 分组注意事项


```

1、关键字where和group by同时出现的时候group by必须在where的后面

where先对整体数据进行过滤之后再分组操作

 

2、where 筛选条件不能使用筛选条件


3、聚合函数只能在分组之后使用

select id,name,age from emp where max(salary) > 3000; 报错

   select max(salary) from emp; # 不分组默认整体就是一组


 

# 题目: 统计各部门年龄在30岁以上的员工平均薪资

1、先求所有年龄大于30岁的员工

    select * from emp where age>30;

   2、在对结果进行分组

    select * from emp where age>30 group by post;

   3、最终结果

    select post,avg(salary) from emp where age>30 group by post;

```


### having 分组之后的筛选


```

"""

having的语法和where是一致的,只不过having是在分组之后进行的过滤操作

即having是可以直接使用聚合函数的

聚合函数:max,avg,sum,count

"""




# 题目: 统计各部门年龄在30岁以上的员工工资,并且保留平均工资大于10000的部门

select post,avg(salary) from emp

 where age>30

    group by post

       having avg(salary) >10000

       ;

```


### distinct去重


```

"""

一定注意 必须是完全一样的数据才可以去重

一定不要将主键忽视,有主键存在的情况下是不能去重,因为主键都是不同的

[

{'id':1,'name':'jason','age':18},

{'id':2,'name':'jason','age':18},

{'id':3,'name':'egon','age':18}

]

"""


# 这一行有主键,无法去重

select distinct id,age from emp;


# 这一行无主键,可以去重

select distinct age from emp;



```


### order by 排序


```

select * from emp order by salary;

select * from emp order by salary asc;

select * from emp order by salary dasc;

"""

order by 默认是升序 asc 该asc可以省略不写

也可以修改为降序 desc

"""

select * from emp order by age desc,salary asc;

# 先按照age降序排  如果碰到age相同,则按照salary升序排,后面还可以再跟



# 题目: 统计各部门年龄再10岁以上的员工平均工资,并且保留平均工资大于1000的部门,然后对平均工资降序排序

select post,avg(salary) from emp

 where age>30

    group by post

       having avg(salary) >10000

       order by avg(salary) desc

       ;


```


### limit限制展示条数


```


select * from emp;

"""当数据量多的时候容易造成卡死现象"""

select * from emp limit 3 # 只展示三条数据


select * from emp limit 0,5; #从0的位置往后取5条


select * from emp limit 5,5; #从5的位置往后取5条


1、第一个参数是起始位置

2、第二个参数是条数


```


### 正则


```

select * from emp where name regexp '^j.*(n|y)$';

j开头,n或者y结尾,*代表所有


```


### 多表查询


```

select * from dep,emp; # 结果 笛卡尔积


select * from emp,dep where emp.dep_id = dep.id;


"""

Mysql正对拼表操作专门开设了对应的方法

   inner join  内连接

   left join  左连接

   right join  右连接

   union   全连接

"""


# inner join 内连接

# 只拼接两张表中共有的数据

select * from emp inner join dep on emp.dep_id = dep.id;



# left join 左连接

# 左表所有的数据都展示出来,没有对应的项就用NULL

select * from emp left join dep on emp.dep_id = dep.id;


# right join 右连接

# 右表所有的数据都展示出来,没有对应的项就用NULL

select * from emp right join dep on emp.dep_id = dep.id;


# union 全连接

# 左右两张表的所有数据都展示出来

select * from emp left join dep on emp.dep_id = dep.id

union

select * from emp right join dep on emp.dep_id = dep.id;

```


### 子查询


```

"""

子查询就是我们平时解决问题的思路

分步骤解决问题

 第一步

 第二部

 ...

将一个查询语句的结果当作另一个查询语句的条件使用

"""


# 题目:查询部门是技术或者人力资源的员工信息

1、获取部门的id号

   2、再去员工表里面筛选出对应的员工

   select id from dep where name='技术' or name='人力资源';

   select name from emp where dep_id in (200,201);

 

   select * from emp where dep_id in (select id from dep where name='技术' or name='人力资源');

```


### 总结


```

表的查询结果可以作为其他表的查询条件

也可以通过起别名的方式把他作为一张虚拟表跟其他表关联


# 查询平均年龄再25岁以上的部门名称

"""只要是多表查询就有两种思路  连表,子查询"""

# 连表操作

1、先拿到部门和员工表 拼接之后的结果

   2、分析语义 得出需要进行分组

    select dep.name from emp inner join dep

        on emp.dep_id = dep.id

           group by dep.name

           having avg(age) > 25

           ;

 """涉及到多表操作的时候,一定要加上表的前缀"""

     

# 子查询

   select name from dep where id in

       (select dep_id from emp group by dep_id

           having avg(age)>25);

     

# 关键字 exist(了解)

只返回布尔值 True False

   返回True的时候外层查询语句执行

   返回False的时候外层查询语句不再执行

   select * from emp where exists

    (select id from dep where id>3);

```


## Navicat软件


```

1、MySQ是不区分大小写的

验证码忽略大小写

    内部统一转大写或者小写比较即可

        upper

           lower

         

2、MySQL建议所有的关键字大写


3、MySQL中的注释有两种

--

   #

4、再navicat中如何快速注释和解注释

ctrl + ? 加注释

   ctrl + ? 基于以上操作再来一次解注释

   ctrl + shift + ? 老版本解开注释

```


## pymysql模块


```

"""

支持python代码操作数据库MySQL

"""



import pymysql


conn = pymysql.connect(

   host="127.0.0.1",

   port=3306,

   user='root',

   password='Huawei12#$',

   database='goods_management',

)  # 连接数据库


cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 产生一个游标对象(就是用来执行命令的)


sql = 'select * from client;'

res = cursor.execute(sql)

print(res)  # execute 返回当前sql语句影响的行数


print(cursor.fetchone())  # 只拿一条

print(cursor.fetchall())  # 拿所有

print(cursor.fetchmany(2))  # 指定拿2条


# 读取数据类似于文件光标的移动

cursor.scroll(1, 'relative')  # 相对于光标所在位置继续往后移动一位

cursor.scroll(1, 'absolute')  # 相对于数据的开头往后移动一位

```




## sql注入问题


```

"""

利用语法的特性,书写一些特点的语句实现固定的语法

利用MySQL的注释语法

"""

select * from passwd where name='asd' or 1=1 -- asdasd' and password=''


日常生活中很多软件在注册的时候都不含有特殊符号

因为容易构造出特定的语句入侵数据库 不安全


# 敏感的数据不要自己做拼接,交给execute方法即可

rows = cursor.execute(sql,(username,password))




例子:


import pymysql


conn = pymysql.connect(

   host="127.0.0.1",

   port=3306,

   user='root',

   password='Huawei12#$',

   database='goods_management',

)  # 连接数据库


cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 产生一个游标对象(就是用来执行命令的)


username = input('>>>:')

password = input('>>>:')


sql = "select * from passwd where name=%s and password=%s"


# 不要手动拼接数据 先%s占位,之后将需要凭借的数据交给execute方法即可

rows = cursor.execute(sql,(username,password))  # 自动识别sql里面的%s用后面的元组里面的数据替换

print(sql)

if rows:

   print('登陆成功')

   print(cursor.fetchall())

else:

   print('登录失败')



```


## pymysql模块增删改查数据操作


```

import pymysql


conn = pymysql.connect(

   host="127.0.0.1",

   port=3306,

   user='root',

   password='Huawei12#$',

   database='goods_management',

   # autocommit=True

)


cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 产生一个游标对象(就是用来执行命令的)


# 增

sql = 'insert into passwd(name,password) values(%s,%s)'

# rows = cursor.execute(sql,('admin',123))

rows = cursor.executemany(sql,[('xxx',123),('ooo',123)])    #以下增加2条

print(rows)

conn.commit()   # 确认


# 修改

sql = 'update passwd set name="hwnb" where id=2'

rows = cursor.execute(sql,)

print(rows)

conn.commit()


# 删

sql = 'delete from passwd where id=2'

rows = cursor.execute(sql,)

print(rows)

conn.commit()


# 查

sql = 'select * from passwd'

cursor.execute(sql)

print(cursor.fetchall())


"""

增删改查中

   增 删 改 他们的操作涉及到数据的修改

   需要二次确认

   # conn.commit()   # 确认

   如果再上面加上autocommit=True后续则不需要确认

"""


1、增删改需要二次确认才能操作

2、批量增

rows = cursor.executemany(sql,[('xxx',123),('ooo',123)])

```


## 视图(了解)


```

1、什么是视图

视图就是哦通过查询得到一张虚拟表,保存下来,下次直接使用

视图也是表


2、为什么要用

频繁操作一张虚拟表,这样就可以做成视图,后续直接操作


3、怎么用

固定语法

create view 视图名 as 虚拟表的查询sql语句


4、使用频率

不高

当创建很多视图之后,会造成表的不好维护


注意:

1、视图再硬盘上只有表结构,没有数据(数据还是来自于之前的表)

2、视图只用来查询 里面的数据不要修改,可能会影响到真正的表



```




## 触发器(了解)


```

是什么:

再满足对表数据进行增、删、改的情况下,自动触发的功能


有啥用:

可以帮助我们实现监控、日志...


语法结构:

触发器可以再六种情况自动触发

增前,增后,删前,删后,改前,改后

create trigger 触发器的名字 before/after insert/update on 表名

for each row

begin

 sql语句

end



ps:修改MySQL默认的语句结束符,只作用于当前窗口

delimiter $$  将默认的结束符号由;改为$$



# 案例

CREATE TABLE cmd(

id int primary key auto_increment,

user char(32),

priv char(10),

cmd char(64),

sub_time datetime, # 提交事件

success enum('yes','no') # no代表执行失败

);


create table errlog(

id int primary key auto_increment,

err_cmd char(64),

err_time datetime

);


"""

当cmd表中的记录succes字段是no那么触发触发器的执行取errlog表中插入数据

NEW指代的是一条条数据对象

"""


delimiter $$

create trigger tri_after_insert_cmd after insert on cmd

for each row

begin

if NEW.success = 'no' then

    insert into errlog(err_cmd,err_time)

values(NEW.cmd,NEW.sub_time);

end if;

end $$

delimiter;



# 删除触发器

drop trigger tri_after_insert_cmd

```




## 事务(需要掌握)


```

是什么:

   开启一个事务可以包含多条sql语句 这些sql语句要么同时成功

   要么一个都别想成功


作用:

保证了对数据操作的安全性

 

事务的四大特性:

ACID

   A:原子性

       一个事务是不可分割的单位,事务中包含这诸多操作

       要么同时成功要摸同时失败

   C:一致性

       事务必须是使数据库从一个一致性状态变到另一个一致性状态

       一致性跟原子性密切相关

   I:隔离性

       一个事务的执行不能为其他事务干扰

   D:持久性

       也叫"永久性"

       一个事务一旦提交成功执行成功 那么他是将数据刷到硬盘中的,不会丢数据

     

如何使用:

1、开启事务

    start transaction;

   2、回滚(回到事务发生之前的状态)

    rollback;

   3、确认(确认之后就无法回滚)

    commit;


"""模拟转账功能"""


create table user(

id int primary key auto_increment,

   name char(16),

   balance int

);

insert into user(name,blance) values

('jason',1000),

('egon',1000),

('tank',1000);


#1、先开启事务

start transaction;


#2、多条sql语句

update user set balance=900 where name = 'jason';

update user set balance=1010 where name='egon';

update user set balance=1090 where name='tank';


#3、回滚

rollback;


#4、确认

commit;


总结:

当你想让sql语句保持一致性的时候可以使用事务


```




## 存储过程(了解)


```

是什么

类似于python中的自定义函数

它的内部包含了一系列可以执行的sql语句,存储过程放于MySQL服务端中,可以直接通过存储过程触发内部sql语句执行



怎么用

固定语法

create procedure 存储过程的名字(形参1,形参2,....)

begin

 sql代码

end


ps:修改MySQL默认的语句结束符,只作用于当前窗口

delimiter $$  将默认的结束符号由;改为$$



# 调用

call 存储过程的名字


三种开发模型

1、第一种

 应用程序:程序员写代码开发

 MySQL:提前编写好存储过程,供应用程序调用

 优点:提升开发效率

 缺点:考虑到认为因素,跨部门沟通问题,后续的存储过程扩展性差

2、第二种

 应用程序:程序员写代码开发之外,涉及到数据库操作也自己写

 优点:扩展性高

 缺点:开发效率低,编写sql语句太过繁琐,而且后续还要考虑sql优化问题

3、第三种

 应用程序:只写程序代码,不写sql语句,基于别人写好的操作MySQL的python框架直接操作即可 ORM框架

 优点:开发效率比上面两种情况都高

 缺点:语句的扩展性差,可能会出现效率低下的问题

4、总结

 第一种基本不用,一般都是第三种



"""存储过程具体演示"""

delimiter $$

create procedure p1(

    in m int, # 只进不出 m不返回出去

       in n int,

       out res int, #该形参可以返回出去

   )

begin

 select tname from teacher where tid>m and tid<n;

       set tes=0; #将res变量修改,用来标识当前存储代码执行

end $$

   delimiter ;


# 正对形参res 不能直接传数据,应该传一个变量

# 定义变量

set @res = 10;

# 查看变量

select @res;

# 调用

call p1(1,5,@res)

 


```


## 在pymysql中调用存储过程


```

import pymysql


conn = pymysql.connect(

   host="127.0.0.1",

   port=3306,

   user='root',

   password='Huawei12#$',

   database='goods_management',

   # autocommit=True

)


cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  # 产生一个游标对象(就是用来执行命令的)


# 调用存储过程

cursor.callproc('p1',(1,5,10))

"""

@_p1_0 = 1

@_p1_1 = 5

@_p1_2 = 10

"""

print(cursor.fetchall())

```




## 内置函数(了解)


```python

跟存储过程的区别:存储过程是自定义函数,函数类似于内置函数

```




## 流程控制(了解)


```

# if判断

   delimiter //

   create procedure proc_if()

   begin

       declare i int default 0;

       if i = 1 then

           select 1;

       elseif i = 2 then

           select 2;

       else

           select 7;

       end if;

   end //

   delimiter ;

# while 循环

   delimiter //

   create procedure proc_while()

   begin

       declare num int ;

       set num = 0;

       while num < 0 do

           select

               num;

           set num = num + 1;

       end while;

```




## 索引理论(了解)


```

是什么

数据都是存在硬盘上,我们需要通过索引来找到数据

类似于书的目录

优点:可以通过查询速度降低io操作

索引在MySQL中也叫做'键',是存储引擎用于快速查找记录的一种数据结构

1、primary key

2、unique key

3、index key

ps:foreign key 不是加速查询用的,不在研究范围内

上面三种key,前面两种除了增加查询速度之外各自还有约束条件

最后一种index key没有任何的约束条件,只是用来帮助快速查询速度


本质

通过不断缩小想要的数据范围,筛选出最终的结果,同时将随机事件变成顺序事件

也就是有了索引顺序,我们总可以通过一种固定的方式找到数据

一张表中可以有多个索引


缺点:

1、当表中有大量数据存在的前提下,创建索引速度慢

2、在索引创建完毕之后,写的性能会降低(当插入数据的时候索引需要拆掉重新创)

3、索引不要随意的创建


聚集索引 primary key

聚集索引指的就是主键

innodb 只有两个文件 直接将主键存放在了idb表中

Myisam 三个文件,单独将索引存放在一个文件


辅助索引 unique index

   查询数据的时候不可能一直使用到主键,也可能会用到name,password等其他字段

   这个时候无法用聚集索引,这个时候可以设置辅助索引也是个b+树

 

覆盖索引

在辅助索引的叶子节点上就已经拿到了需要的数据

```

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
SQL 关系型数据库 MySQL
在 MySQL 中使用 IN
【8月更文挑战第12天】
78 0
在 MySQL 中使用 IN
|
5月前
|
关系型数据库 MySQL 数据挖掘
MySQL
MySQL
37 2
|
关系型数据库 MySQL 索引
MySQL为什么不推荐使用in
MySQL为什么不推荐使用in
|
关系型数据库 MySQL 数据库
mysql实用篇
mysql实用篇
|
SQL 关系型数据库 MySQL
【必知必会的MySQL知识】②使用MySQL
【必知必会的MySQL知识】②使用MySQL
106 0
【必知必会的MySQL知识】②使用MySQL
|
关系型数据库 MySQL 数据安全/隐私保护
如何进入 mysql?
如何进入 mysql?
113 0
如何进入 mysql?
|
SQL Oracle NoSQL
《MySQL自传》
我是一只勤劳的小海豚,网名叫MySQL,出生于1995年5月23号,正宗95后,你们可别小看我,我现在可是全世界最流行的开源数据库,全球有800万个实例呢。
1056 2
《MySQL自传》
|
关系型数据库 MySQL
07_mysql中having的使用_having与where的对比
mysql中having的使用 having与where的对比
171 0
07_mysql中having的使用_having与where的对比
|
SQL JSON Oracle
MySQL 8.0来了,逆之者亡...
MySQL 8.0来了,逆之者亡...
185 0
MySQL 8.0来了,逆之者亡...
|
关系型数据库 MySQL 数据库
使用MySQL
使用MySQL
109 0