与python交互之前我们需要安装一个MySQL的驱动模块Connector,这个驱动模块直接在cmd命令行输入
pip
install
mysql.connector
安装是否成功可以接着输入
python
# 输入之后,会进入python解释器(前提是python已经配置好了环境变量
# 导入安装的模块,没有报错即安装成功
import mysql.connector
进入自己的编辑器(pycharm)首先连接数据库方式:
数据库连接
1、当前模块直接连接
import mysql.connector # 连接数据库 con = mysql.connector.connect( host = " 127.0.0.1 " , port =3306 , user = " root " , # 可以填写其他用户,用户的变量名是user password= " XXXXXX " , # 这里填写上面用户对应的密码 database= " dbname " # 需要连接的数据库的名字 ) ...... ...... ...... # 使用完数据库之后,需要关闭数据库,不要浪费资源 con.close()
2、导入配置文件进行连接
# 先创建一个配置文件 config.py import mysql.connector # 下面是字典类型 config = { " host " : " 127.0.0.1 " , " port " : 3306 , " user " : " root " , " password " : " XXXXXX " , " database " : " dbname " } # 再创建一个文件connect.py import mysql.connector from config import config # 使用配置文件连接 con = mysql.connector.connect(** config) # 关闭连接 con.close()
游标
游标的作用是执行sql语句,或者保存sqi结果集。常用的方法:
cursor()创建游标(使用连接)
execute()执行sql语句;可以接受两个参数,形如下面涉及的预编译
executemany()循环执行相同的sql语句第二个参数必须是一个列表
fetchall()/fetchone()获取全部数据/一条数据
# 创建一个游标 cursor = con.cursor() # 假设有两个sql语句一个是查询,一个是执行insert语句 cursor.execute(sql_select) # 这个结果集是保存在cursor中,你可以通过fetechall()获取全部数据或者fetchone()查询第一条数据 data = cursor.fetchall() # 得到的数据我们可以进行业务的处理 # 执行创建语句,不会结果集 sql = " insert into s_region values(%s, %s) " data = [[1, " sd " ],[2, " dfd " ]] # 或者里面是元组的形式data = [(1,"sd"),(2,"dfd")] cursor.execute(sql, data)
防止SQL注入攻击方式
为什么存在SQL注入攻击?输入一个不与数据表格的数据匹配也是可以继续执行的。比如用户输入特定的错误字符串格式数据,还是可以通过验证登录进去
import mysql.connector # 连接数据库 # 1、本模块创建连接并保存在变量中 con = mysql.connector.connect( host = " 127.0.0.1 " , port =3306 , user = " root " , password = " 123456 " , database = " briup2 " ) # 2、创建数据库游标 cursor = con.cursor() # 模拟登录:账户:last_name,密码:first_name username = " 1 or 1=1 " password = " 1 or 1=1 " # 3、定义一个sql语句 sql = " select count(*) from user_table where user_id=%s and user_psd=%s " % (username, password) # 4、执行sql语句 ursor.execute(sql ) # 5、获取全部结果集 data = cursor.fetchall() print (data) # 总之结果不为0
上述结果不为0表示后台可以查到某个结果集,即用户是可以登录进入(主页);如果可以注入攻击就可以删掉某个数据表的所有数据,这样做是很危险的,所以需要后台处理得到的数据
id = " 1 or 1=1 " sql = " delete from tbname where id=%s " % (id) # 将订单表数据全部删除了--欲哭无泪 delete from tbname where id=1 or 1=1
防止SQL注入攻击的三种方式:
1、通过单引号将获取的值转换为字符串:format格式
# 将上面的sql语句改成下面这一语句,注意大括号两边都有引号 sql = " select count(*) from user_table where user_id=’{}‘ and user_psd='{}' " .format(username, password)
2、通过单引号将获取的值转换为字符串:字符串格式
# 将上面的sql语句改成下面这一语句,注意%s两边都有引号 sql = " select count(*) from user_table where user_id=’%s‘ and user_psd='%s' " %(username, password)
3、通过预编译的方式防止SQL注入攻击(推荐使用)
# 将上面的sql语句改成下面这一语句,注意%s两边都没有引号 sql = " select count(*) from user_table where user_id=%s and user_psd=%s " # 再将执行语句改成下面这条 cursor.execute(sql, (username, password))
事务控制
事务的产生是因为对数据表操作之后,数据库不会发生改变,若想发生改变,就需要事务三操作
事务控制一般有三步操作:
1、开启事务:通过连接开启事务,调用start_transaction()
2、提交事务:也是通过连接提交事务,一般都是适用于对数据表的增加、删除、修改等操作,调用commit()
3、回滚事务:一般是发生异常之后才会执行的回滚,调用rollback()
这三步都应该在异常中执行
import mysql.connector # 连接数据库 try : """ 数据库的连接,数据表的增加、删除、修改操作 都是需要在异常中处理 """ # 1、本模块创建连接并保存在变量中 con = mysql.connector.connect( host = " 127.0.0.1 " , port =3306 , user = " root " , password = " 123456 " , database = " briup2 " ) # 2、创建数据库游标 cursor = con.cursor() # 3、开启事务 con.start_transaction() # 4、执行一条update语句 sql = " update user_table set username='aaa' " # 5、执行sql语句 cursor.execute(sql) # 6、提交事务 con.commit() except : """ 在发生异常之前,还需判断连接是否成功 发生异常之后一般都是需要回滚,以免数据发生错误 """ if " con " in dir(): con.rollback() finally : """ 无论异常与否,都要执行finally语句 """ con.close()
数据库连接池(缓存)
上述代码的开头都会写创建数据库的连接和最后也会写数据库的关闭,如果程序反复创建和关闭,是会浪费大量的资源。而数据库连接池是在程序运行之前就已经缓存好了,那么就可以直接获取连接就行,而且不使用数据库也不用关闭,缓存机制会自动回收
# 先创建一个配置文件 config.py config = { " host " : " 127.0.0.1 " , " port " : 3306 , " user " : " root " , " password " : " 123456 " , " database " : " briup2 " } # 在创建一个测试文件 exam.py import mysql.connector.pooling from config import config pool = mysql.connector.pooling.MySQLConnectionPool( ** config, pool_size =10 ) try : # 2、先获取一个连接 con = pool.get_connection() # 3、开启事务 con.start_transaction() # 4、创建一个游标 cursor = con.cursor() # 5、定义sql语句 sql_create = " create table s_emp_new like s_emp; " sql_insert = """ insert into s_emp_new select * from s_emp where dept_id in ( select dept_id from s_emp group by dept_id having avg(salary)>( select avg(salary) from s_emp ) ) """ sql_update = " update s_emp_new set dept_id = 44 " # 6、执行sql语句 cursor.execute(sql_create) cursor.execute(sql_insert) cursor.execute(sql_update) # 7、提交事务 con.commit() tip = " 执行成功! " except Exception as e: if " con " in dir(): # 8、回滚事务 con.rollback() tip = " 执行失败! " print (e) finally : print (tip)