MySpl与PyCharm交互

1 > python操做MySql

   python中支持操作MySQL的模块很多 其中最常见的当属’pymysql’。

1.1 > 基本使用

   1 > 连接服务端


	import	pymysql
	conn_obj = pymysql.connect(
		host='127.0.0.1',		# MySql服务端的IP地址
		port=3306,			# MySql默认的PORT地址(端口号)
		user='root',			# 用户名
		password='mysqlabc',	# 密码 也可以简写password
		database='jp04_3',		# 库名称 也可以简写成db
		charset='utf8'			# 字符编码 千万不要加杠utf-8
	)	# 要善于查看源码获取信息
	

   2 > 产生获取命令的游标对象


	cursor = conn_obj.cursor(
		cursor=pymysql.cursor.DictCursor
	)	
	'''
	 括号内不写参数 数据是元组要元组 不够精确不能标识数据的含义
	 添加参数则会将数据处理成字典
	'''

   3 > 编写SQL语句。


	sql1 = 'show tables;'
	# sql1 = 'select * from teacher;'	# SQL语句会被高亮显示 不用惊慌
	# sql1 = 'select * from score;'		# SQL语句会被高亮显示 不用惊慌

   4 > 执行SQL语句。


	affect_rows = cursor.execute(sql1)
	print(affect_rows)  # 执行SQL语句之后受影响的行数

   5 > 获取结果


	res = cursor.fetchall()
	print(res)

在这里插入图片描述

1.2 > 补充说明


	获取SQL语句执行的结果 跟读取文件内容的read方法几乎一致(光标)
	fetchone()						# 展示一条数据
	fetchmany()						# 展示多条数据 括号内可填写具体几条数据
	fetchall()						# 展示所有数据
	cursor.scroll(1, 'relative') 	# 相对于当前位置往后移动一个单位
	cursor.scroll(1, 'absolute') 	# 相对于起始位置往后移动一个单位
	

2 > SQL注入问题

2.1 > 用户登录注入问题

   当我们利用数据库编写用户登录的代码的时候,用户需要匹配用户名和密码才可以登录,但是由于SQL注入问题的存在可能不需要匹配也可以登录成功。
   用户登录代码如下:


import pymysql

conn_obj = pymysql.connect(
    host='127.0.0.1',
    port=3306,
    user='root',
    password='mysqlabc',
    db='jp04_3',
    charset='utf8'
)
cursor = conn_obj.cursor(
    cursor=pymysql.cursors.DictCursor
)
name = input('请输入登录的用户名 >>>>>:').strip()
pwd = input('请输入用户名的密码 >>>>>:').strip()
# 拼接查询语句

sql = "select * from userinfo where username = '%s' and pwd = '%s'"%(name,pwd)
# 执行sql语句
res = cursor.execute(sql)
if res:
    print('登录成功')
else:
    print('用户名或密码错误')

在这里插入图片描述

   情况一:写正确的用户名错误的密码也可以登录。


	用户名: bob' -- jhahsdjasdjasd
	密码: 直接回车

在这里插入图片描述
   情况二:用户名和密码都不需要也可以登录


	用户名:xxx' or 1=1 -- asdjasjdkajsd
	密码:直接回车

在这里插入图片描述
   上述两种情况是典型的SQL注入问题。其实就是利用MySQL注释语法及逻辑运算符钻的漏洞。

  ; 解决SQL注入的问题其实也很简单 就是想办法过滤掉特殊符号。


	execute方法自带校验SQL注入问题 自动处理特殊符号
	 	ps:设计到敏感数据的拼接 全部交给execute方法即可!!!
    		sql = "select * from userinfo where name=%s and password=%s;"
			cursor.execute(sql, (name, password))

2.2 > execute方法补充(了解)


	批量插入数据
		sql = 'insert into userinfo(name,password) values(%s,%s)'
		cursor.executemany(sql,[('tom',123),('lavin',321),('pony',333)])
		

3 > 二次确认

   数据的增删改查四个操作是有轻重之分的。


	查                           不会影响真正的数据 重要程度最低
    增、改、删                    都会影响真正的数据 重要程度较高
	
	pymysql针对增、改、删三个操作 都设置了二次确认 如果不确认则不会真正影响数据库

   方式1:代码直接编写


	affect_row = cursor.execute(sql)
	conn_obj.commit()  # 手动二次确认
	

   方式2:配置固定参数


	conn_obj = pymysql.connect(
    autocommit=True  # 自动二次确认
)


4 > 修改表SQL语句补充


	# 1.修改表的名字  rename
	alter table t1 rename ttt;

	# 2.添加字段		 add
	alter table ttt add pwd int;  '''默认是尾部追加字段'''
	alter table ttt add tid int after name;  '''指定追加位置'''
  	alter table ttt add nid int first;  '''指定头部添加字段'''

	# 3.修改字段		 change(名字类型都可)/modify(只能改类型不能改名字)
	alter table ttt change pwd password tinyint;

	# 4.删除字段			 drop
	alter table ttt drop nid;
	

5 > 视图

   我们将通过SQL语句的执行得到的一张虚拟表 保存下来之后就称之为 —— 视图。


	视图的作用
		如果需要频繁的使用一张虚拟表 可以考虑制作成视图 降低操作难度
		eg: emp与dep表拼接

	视图的制作
		create view 视图名 as sql语句


   视图虽然看似很好用 但是会造成表的混乱 毕竟视图不是真正的数据源
   视图只能用于数据的查询 不能做增、删、改的操作 可能会影响原始数据(视图里面的数据是直接来源于原始表 而不是拷贝一份)

6 > 触发器


触发器概念
	在对表数据进行增、删、改的具体操作下,自动触发的功能
	
触发器作用
	专门针对表数据的操作 定制个性化配套功能

触发器种类
	表数据新增之前、新增之后
	表数据修改之前、修改之后
	表数据删除之前、删除之后

触发器创建
	create trigger 触发器名字 before/after insert/update/delete
	on 表名 for each row
		begin
			SQL语句
		end
	触发器的名字一般情况下建议采用下列布局形式
		tri_after_insert_t1
		tri_before_update_t2
		tri_before_delete_t3

   具体案例(了解)

	"""
		补充:临时修改SQL语句的结束符
			delimiter $$
		临时修改的原因是因为触发器 存储过程等技术点 代码中也需要使用分号
		如果不修改 则无法书写出完成的代码
	"""
	1.先创建两张表
	
    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') #0代表执行失败
    );

    CREATE TABLE errlog (
        id INT PRIMARY KEY auto_increment,
        err_cmd CHAR (64),
        err_time datetime
    );

	2.需求:cmd表插入数据的success如果值为no 则去errlog表中插入一条记录
		delimiter $$  # 将mysql默认的结束符由;换成$$
	    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 ;  # 结束之后记得再改回来,不然后面结束符就都是$$了

	3.仅仅往cmd表中插入数据
		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');

在这里插入图片描述
   触发器其他补充。


	查看当前库下所有的触发器信息
    	show triggers\G;
    删除当前库下指定的触发器信息
    	drop trigger 触发器名称;

7 > 事务

 	事务的概念
		事务可以包含诸多SQL语句并且这些SQL语句
		要执行成功 要么同时执行失败 这是事务的原子性特点
	
	事务的作用
		戴某某欠了赵某某一笔钱 现在想要还钱
			戴某某拿着交行的银行卡去招商银行的ATM机给赵某某的建行卡转钱
				1.朝交行的服务器发送请求 修改戴某某账户余额(减钱)
				2.朝建行的服务器发送请求 修改赵某某账户余额(加钱)

7.1 > 事务的四大特性(重点)

ACID
	A:原子性
		一个事务是一个不可分割的整体 里面的操作要么都成立要么都不成立
	C:一致性
		事务必须使数据库从一个一致性状态变到另外一个一致性状态
	I:隔离性
		并发编程中 多个事务之间是相互隔离的 不会彼此干扰
	D:持久性
		事务一旦提交 产生的结果应该是永久的 不可逆的

7.2 > 具体使用案例


	1.创建表及录入数据
  	create table user(
      id int primary key auto_increment,
      name char(32),
      balance int
      );
    insert into user(name,balance)
      values
      ('jason',1000),
      ('kevin',1000),
      ('tank',1000);

在这里插入图片描述

	2.事务操作
  	开启一个事务的操作
    	start transaction;
    编写SQL语句(同属于一个事务)
    		update user set balance=900 where name='jason';
			update user set balance=1010 where name='kevin'; 
			update user set balance=1090 where name='tank';
    事务回滚(返回执行事务操作之前的数据库状态)
    	rollback;  # 执行完回滚之后 事务自动结束
    事务确认(执行完事务的主动操作之后 确认无误之后 需要执行确认命令)
    	commit;  # 执行完确认提交之后 无法回滚 事务自动结束

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

8 > 存储过程

   类似于python中的自定义函数


# 相当于定义函数
delimiter $$
create procedure p1()
begin
	select * from cmd;
end $$
delimiter ;

# 相当于调用函数
call p1()

在这里插入图片描述
   类似于python中的有参函数.


	delimiter $$ 
	create procedure p1(
		in m int,
		in n int,
		out res int # out表示这个参数可以被返回出去,还有一个inout表示即可以传入也可以被返回出去
	)
	begin
		select tname from userinfo where id > m and id < n;
		set res=0;
	end $$
	delimiter;

   针对res需要先提前定义


	set @res=10;  定义
	select @res;  查看
	call p1(1,5,@res)  调用
	select @res  查看

   查看存储过程具体信息


	show create procedure pro1;

   查看所有存储过程


	show procedure status;

   删除存储过程


	drop procedure pro1;

9 > 函数

   注意与存储过程的区别,mysql内置的函数只能在sql语句中使用!

	'''
		我们可以用help 加函数名 查看帮助信息
	'''
	# 1.移除指定字符
	Trim、LTrim、RTrim
	
	# 2.大小写转换
	Lower、Upper
	
	# 3.获取左右起始指定个数字符
	Left、Right
	
	# 4.返回读音相似值(对英文效果)
	Soundex
		"""
		eg:客户表中有一个顾客登记的用户名为J.Lee
		但如果这是输入错误真名其实叫J.Lie,可以使用soundex匹配发音类似的
		where Soundex(name)=Soundex('J.Lie')
		"""	
	# 5.日期格式:date_format
	'''在MySQL中表示时间格式尽量采用2022-11-11形式'''
	CREATE TABLE blog (
	    id INT PRIMARY KEY auto_increment,
	    NAME CHAR (32),
	    sub_time datetime
	);
	INSERT INTO blog (NAME, sub_time)
	VALUES
	    ('第1篇','2015-03-01 11:31:21'),
	    ('第2篇','2015-03-11 16:31:21'),
	    ('第3篇','2016-07-01 10:21:31'),
	    ('第4篇','2016-07-22 09:23:21'),
	    ('第5篇','2016-07-23 10:11:11'),
	    ('第6篇','2016-07-25 11:21:31'),
	    ('第7篇','2017-03-01 15:33:21'),
	    ('第8篇','2017-03-01 17:32:21'),
	    ('第9篇','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');
	
	1.where Date(sub_time) = '2015-03-01'
	2.where Year(sub_time)=2016 AND Month(sub_time)=07;
	# 更多日期处理相关函数 
		adddate	增加一个日期 
		addtime	增加一个时间
		datediff	计算两个日期差值
  ...

10 > 流程控制

   python if判断

	if 条件:
    	子代码
  	elif 条件:
    	子代码
  	else:
    	子代码

   js if判断

	
	if(条件){
    	子代码
  	}else if(条件){
    	子代码
  	}else{
    	子代码
  	}

   MySQL if判断

	
	if 条件 then
        子代码
  	elseif 条件 then
        子代码
  	else
        子代码
  	end if;

   MySQL while循环

	
	DECLARE num INT ;
  		SET num = 0 ;
  	WHILE num < 10 DO
    	SELECT num ;
    	SET num = num + 1 ;
 	END WHILE ;

11 > 索引

   索引就是一种数据结构。


	类似于书的目录。
	意味着以后再查数据应该先找目录再找数据,而不是用翻页的方式查询数据

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


	primary key 	主键
  	unique	key		唯一键
  	index 	key   	索引键
  	'''
		上面三种key前两种除了有加速查询的效果之外
		还有额外的约束条件
		(primary key:非空且唯一,unique key:唯一),
		而index key没有任何约束功能只会帮你加速查询

		foreign key不是用来加速查询用的,不在我们研究范围之内
	'''

   索引的基本用法:


	id		name	pwd		post_comment  addr  age 
		
	基于id查找数据很快 但是基于addr查找数据就很慢 
  	解决的措施可以是给addr添加索引
	'''
	索引虽然好用 但是不能无限制的创建!!!
	'''
	
**索引的影响:**
	* 在表中有大量数据的前提下,创建索引速度会很慢
	* 在索引创建完毕后,对表的查询性能会大幅度提升,但是写的性能会降低

   索引的底层数据结构是b+树。


	b树 红黑树 二叉树 b*树 b+树
	上述结构都是为了更好的基于树查找到相应的数据

	'''
		只有叶子结点存放真实数据,根和树枝节点存的仅仅是虚拟数据
		查询次数由树的层级决定,层级越低次数越少
		一个磁盘块儿的大小是一定的,那也就意味着能存的数据量是一定的。如何保证树的层级最低呢?
		一个磁盘块儿存放占用空间比较小的数据项
		思考我们应该给我们一张表里面的什么字段字段建立索引能够降低树的层级高度>>> 主键id字段
	'''

11.1 > 索引分类和作用

	
	聚集索引(primary key)
	辅助索引(unique key,index key)
		'''
		查询数据的时候不可能都是用id作为筛选条件,
		也可能会用name,password等字段信息,
		那么这个时候就无法利用到聚集索引的加速查询效果。
		就需要给其他字段建立索引,这些索引就叫辅助索引

		叶子结点存放的是辅助索引字段对应的那条记录的主键的值
		(比如:按照name字段创建索引,那么叶子节点存放的是:
		{name对应的值:name所在的那条记录的主键值})
		数据查找 如果一开始使用的是辅助索引 那么还需要使用聚焦索引才可以获取到真实数据
		'''
	覆盖索引:只在辅助索引的叶子节点中就已经找到了所有我们想要的数据
	非覆盖索引:虽然查询的时候命中了索引字段name,但是要查的是age字段,所以还需要利用主键才去查找
		select age from user where name ='jason';
	

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值