MySQL微讲解(五)

MySQL微讲解(五)

python操作MySQL

import pymysql

conn_obj = pymysql.connect(
    host='127.0.0.1',  # MySQL服务端的IP地址
    port=3306,  # MySQL默认的端口号
    user='root',  # 用户名
    password='root',  # 密码
    database='ji02',  # 数据库名
    charset='utf8'  # 字符编码,注意不要写成utf-8的格式,会报错
)
cursor = conn_obj.cursor(  # 括号内不写参数,输出的数据是元组套元组
    cursor=pymysql.cursors.DictCursor  # 括号内加入参数,输出的数据就会处理成字典,便于识别
)
sql1 = 'select * from class'  # 编写SQL语句,会高亮显示,但不会报错,结尾可以加分号,也可以不加
affect_rows = cursor.execute(sql1)  # execute会执行SQL语句,会自动识别SQL语句是否有分号
print(affect_rows)  # 输出执行SQl语句之后受影响的行数
# print(cursor.fetchall())  # 获取结果集中的所有数据
# print(cursor.fetchone())  # 获取结果集中的第一个数据
# print(cursor.fetchmany(2))  # 获取结果集中指定个数的数据
cursor.scroll(1,'relative')  # 相对于当前位置往后移动一个单位
print(cursor.fetchall())
cursor.scroll(1,'absolute')  # 相对于起始位置往后移动一个单位
print(cursor.fetchall())

SQL注入问题

# 1.先创建一个基于数据库的登录jinc
	1.数据库代码
    create table login(
    id int primary key auto_increment,
    name varchar(255),
    password int
    );
    insert into login(name,password) values('oscar',123);
    
    2.python代码
    import pymysql

    conn_obj = pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='root',
        database='jp03',
        charset='utf8'
    )
    cursor = conn_obj.cursor(
        cursor=pymysql.cursors.DictCursor
    )
    username = input('username>>>:').strip()
    password = input('password>>>:').strip()
    sql = "select * from login where name = '%s' and password = '%s';"%(username,password)
    cursor.execute(sql)
    res = cursor.fetchall()
    if res:
        print('登录成功')
    else:
        print('用户名或密码错误')

# 写正确的用户名和错误的密码也可以登录成功
	用户名:oscar' -- asfsdcxddfweacs
	密码:直接回车
# 用户名和密码都不需要也可以登录成功
	用户名:asdx' or 1=1 -- ascascdcasc
    密码:直接回车
# 注入问题
	上面两种情况就是MySQl典型的注入问题,利用的是MySQL注释语法及逻辑运算符
    execute方法自带校验SQL注入问题,会自动处理特殊符号,所以上述代码我们只要稍作修改就可以解决问题:sql = "select * from login where name = %s and password = %s;"
    cursor.execute(sql(username,password))

二次确认

# 1.操作的等级划分
	数据的增删改查四个操作是有轻重之分的,'查'不会真正的影响数据,重要程度低,'增、删、改'都会真正的影响数据,重要程度较高,pymysql针对增、改、删这三个操作,都设置了二次确认的操作,如果二次确认不通过就不会真正的影响数据库
# 2.添加二次确认的操作
	方式一:代码直接编写
        affect_row = cursor.execute(sql)
        conn_obj.commit()  # 受到二次确认
	方式二:配置固定参数
        conn_obj = pymysql.connect(
        	autocommit = True  # 字典二次确认
        )

修改表的SQL语句

# 1.修改表的名字
alter table 旧表名 rename 新表名;
# 2.添加字段
alter table 表名 add 字段名称 字段类型;  # 默认是尾部追加字段
alter table 表名 add 字段名称 字段类型 after 追加位置的字段名称;  # 指定追加位置
alter table 表名 add 字段名称 字段类型 first;  # 指定头部添加字段
# 3.修改字段
	修改字段有两个关键字,'change'和'modify',change可以修改字段名称和字段类型,modify只能修改字段类型,不能修改字段名称
    alter table 表名 change 旧字段名称 新字段名称 新字段类型;
    alter table 表名 modify  字段名称 新字段类型;
# 4.删除字段
	alter table 表名 drop 字段名称;

视图

# 1.视图的概念
	通过SQL语句的执行得到的一张虚拟表,保存下来之后就称之为'视图'
# 2.视图的作用
	如果频繁的操作、使用一张虚拟表,可以考虑制作成视图,降低操作难度
# 3.视图的制作
	create view 视图名 as SQL语句
# 4.视图的缺点
	视图虽然很好用,但是不建议多建立,因为会造成表的混乱,毕竟视图不是真正的数据;视图只能用于数据的查询,不能做增、删、改的操作,因为可能会影响到原始的数据,视图里面的数据是直接来源于原始表的,并不是拷贝的。

触发器

# 1.触发器的概念
	在对表数据进行增、删、改的具体操作下,自动触发的功能
# 2.触发器的作用
	专门针对表数据的操作,定制个性化配套功能
# 3.触发器的种类
	1.表数据新增之前、之后
    2.表数据修改之前、之后
    3.表数据删除之前、之后
# 4.触发器创建
	create trigger 触发器名字 before/after insert/update/delete
    on 表名 for each row 
    	begin
        	SQL语句
        end
'''
触发器的名字一般情况下建议采用下列布局:
tri_after_insert
tri_before_update
tri_before_delete
'''
# 5.代码演示
	1.临时修改SQL语句的结束符
    	delimiter $$
        临时修改结束符的原因是因为创建触发器需要使用到分号,如果不修改就没有办法书写书完整的代码。
	2.创建两张表
    create table cmd(
    id int primary key auto_increment,
    user char(32),
    priv char(32),
    cmd char(32),
    sub_time datetime,
    success enum ('yes','no')
    );
    create table errlog(
    id int primary key auto_increment,
    err_cmd char(32),
    err_time datetime
    );
    3.需求:cmd插入数据的时候,如果'success'的值是'no',就去errlog表中也插入一条记录
        delimiter $$  # 修改结束符号
        create trigger tri_after_insert_cmd after insert on cmd for each row
            begin
                 if NEW.success = 'no' then  # 新纪录都会被MySQL封装成NEW对象
                     insert into errlog(err_cmd,err_time) values(NEW.cmd,NEW.sub_time);
                 end if;
             end $$
         delimiter ;  # 修改结束符号
        # 往cmd表中插入数据,发现errlog表中也有了两条数据
        insert into cmd(user,priv,cmd,sub_time,success) values ('kevin','0755','ls -l /etc',NOW(),'yes'),('kevin','0755','cat /etc/passwd',NOW(),'no'),('kevin','0755','useradd xxx',NOW(),'no'),('kevin','0755','ps aux',NOW(),'yes');
# 6.删除当前库下指定的触发器
	1.查询当前库下所有的触发器信息
    	show triggers\G;
	2.删除当前库下指定的触发器信息
    	drop trigger 触发器名称;

事物

# 1.事务的概念
	事务可以包含诸多SQL语句,并且这些SQL语句要么同时执行成功,要么同时执行失败,这是事务的原子性特点
# 2.事务四大特性
	1.原子性:一个事务是一个不可分割的整体,里面的操作要么都成立,要么都不成立
	2.一致性:事务必须使数据库从一个一致性状态变到另一个一致性状态
	3.隔离性:并发编程中,多个事务之间是相互隔离的,不会彼此干扰
	4.持久性:事务一旦提交,产生的结果应该是永久性的、不可逆的
# 3.代码演示
create table user(
    id int primary key auto_increment,
    name char(255),
    balance int);
insert into user(name,balance) values('oscar',1000),('jason',1000),('tom',1000);

start transaction;  # 开启一个事务
rollback;  # 事务回滚,返回执行事务之前的数据库状态,执行完回滚事务之后,事务自动结束
commit;  # 确认事务,执行完确认事务之后,就没有办法执行回滚事务了,事务自动结束

存储过程

# 相当于定义函数
delimiter $$
create procedure z1()
begin
     select * from cmd;
end $$
delimiter ;
call z1()  # 相当于调用函数
# 类似于有参函数
delimiter $$
create procedure z2(
     in m int,  # in表示这个参数必须只能是传入不能被返回出去
     in n int,
     out res int  # out表示这个参数可以被返回出去,还有一个inout表示既可以传入,也可以被返回出去
)
     begin
         select user from cmd where id > m and id < n;
         set res = 0;  # 用来标志存储过程是否执行
     end $$
delimiter ;
set @res=10;  # 定义,针对res需要提前定义
select @res;  # 查看
call z2(3,2,@res);  # 调用
show create procedure z2;  # 查看存储过程具体信息
show procedure status;  # 查看所有存储过程
drop procedure z2;  # 删除存储过程

函数

	注意与存储过程的区别,mysql内置的函数只能在sql语句中使用
# 1.查看帮助信息
help 函数名
# 2.移除指定字符
Trim、LTrim、RTrim
# 3.大小写转换
Lower、Upper
# 4.返回读音相似值(对英文有效)
Soundex
例子:客户表中有一个顾客的用户名是J.Lee,但如果是输错了,真实姓名其实是J.Lie,可以使用Soundex匹配发音类似的:
        where Soundex(name) = Soundex('J.Lie');
# 5.日期格式
create table blog(
    id int primary key auto_increment,
    name varchar(255),
    sub_time datetime
    );
INSERT INTO blog (NAME, sub_time)
    VALUES
         ('one','2015-03-01 11:31:21'),
         ('two','2015-03-11 16:31:21'),
         ('three','2016-07-01 10:21:31'),
         ('four','2016-07-22 09:23:21'),
         ('five','2016-07-23 10:11:11'),
         ('six','2016-07-25 11:21:31'),
         ('seven','2017-03-01 15:33:21'),
         ('eight','2017-03-01 17:32:21'),
         ('nine','2017-03-01 18:31:21');
select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_format(sub_time,'%Y-%m');
'''
adddate:增加一个日期
addtime:增加一个时间
datediff:计算两个日期差值
'''

流程控制

# 1.if判断
if 条件 then
	子代码
elseif 条件 then
	子代码
else
	子代码
end if;
# 2.while循环
declare num int;
set num = 0;
while num < 10 do
select num;
set num = num + 1;
end while;

索引

# 1.索引是一种数据结构
	类似于书的目录,意味着以后再查数据应该先找目录再找数据,而不是用翻页的方式查询数据,索引在MySQL中也叫做'键',是存储引擎用于快速找到记录的一种数据。
    primary key  # 主键
    unique ker  # 唯一键
    index key   # 索引键
    上面三种键,前面两种处了有加速查询的效果之外,还有额外的约束条件(primary key:非空且唯一,unique key:唯一),而index key没有任何的约束功能,只会帮你加速查询
# 2.索引的影响
	1.在表中有大量数据的前提下,创建索引速度会很慢
    2.在索引创建完毕后,对表的查询性能会大幅度提升,但是写的性能会降低
# 3.索引的底层数据结构
	索引的底层数据结构是'b+树',还有很多的结构,比如b树,红黑树,二叉树,b*树等等,这些结构都是为了更好地基于树查找到相应的数据。
    只有叶子节点存放真实数据,根和树枝节点存的仅仅是虚拟数据,查询次数由树的层级决定,层级越低次数越少。
    聚焦索引:primary key
	辅助索引:unipue key,index key
	查询数据的时候不可能都是用id作为筛选条件的,也可能会用name,password等等,那么这个时候就无法利用聚集索引的加速查询效果,就需要给其他字段建立索引,这些索引就叫辅助索引。
    叶子节点存放的是辅助索引字段对应的那条记录的主键的值,(比如:按照name字段创建索引,那么叶子节点存放的是:{name对应的值:name所在的那条记录的主键值})数据查找,如果一开始使用的是辅助索引,那么还需要使用聚焦索引才可以获取到真实数据。
    覆盖索引:只在辅助索引的叶子节点中就已经找到了所有我们想要的数据
	非覆盖索引:虽然查询的时候用了索引字段name,但是要查的是age字段,所以还需要利用主键去查找。

这里是IT小白陆禄绯,欢迎各位大佬的指点!!!

posted @ 2022-05-09 22:43  陆禄绯  阅读(29)  评论(0编辑  收藏  举报