MySQL代码操作——python版
1. 前言-初识pymysql
import pymysql
# 1. 连接数据库
conn = pymysql.connect(host='localhost', user='root', password='密码', charset='utf8mb4')
cursor = conn.cursor()
# 2. 创建数据库
"""
cursor.execute("create database db4 DEFAULT CHARSET utf8 COLLATE utf8_general_ci")
cursor.commit()
"""
# 3. 使用数据库,查看数据表
"""
cursor.execute("use db4")
cursor.execute("show tables")
result = cursor.fetchall()
print()
"""
# 4. 进入数据库创建表
cursor.execute("use db4")
sql = """
create table L4(
id int not null primary key auto_increment,
title varchar(128),
content text,
ctime datatime
)default charset=utf8;
"""
cursor.execute(sql)
cursor.commit()
# 5. 查看表
cursor.execute("show tables")
print(cursor.fetchall())
# 其他drop table .... 跳过
# 6. 关闭连接
cursor.close()
conn.close()
核心步骤:
connect()
建立连接cursor()
创建游标execute()
执行SQLfetchall()
获取结果close()
关闭连接
注意:所有操作都要先连接,最后记得关闭!
2. Python代码操作
2-1. 基本步骤
- 建立连接 - 使用
pymysql.connect()
- 创建游标 - 使用
connection.cursor()
- 执行SQL - 使用
cursor.execute()
- 提交事务 - 增删改操作后调用
connection.commit()
- 关闭连接 - 最后调用
connection.close()
示例代码
import pymysql
# 1. 建立连接
connection = pymysql.connect(
host='localhost',
user='username',
password='password',
database='dbname'
)
# 2. 创建游标
cursor = connection.cursor()
# 3. 执行SQL操作
# 查 (SELECT)
cursor.execute("SELECT * FROM users")
results = cursor.fetchall() # 获取所有记录
# 增 (INSERT)
cursor.execute("INSERT INTO users (name) VALUES ('张三')")
connection.commit()
# 改 (UPDATE)
cursor.execute("UPDATE users SET name='李四' WHERE id=1")
connection.commit()
# 删 (DELETE)
cursor.execute("DELETE FROM users WHERE id=1")
# 4. 提交事务
connection.commit()
# 5. 关闭连接
cursor.close()
connection.close()
关键说明
fetchone()
- 获取单条记录fetchall()
- 获取所有记录lastrowid
- 获取最后插入行的ID- 增删改操作必须调用
commit()
才会生效 - 最后必须关闭游标和连接
案例:用户登录系统
在实际项目中,流程如下:
- 第一步:根据项目的功能来设计相对应的 数据库 & 表结构(在项目设计之初就应该确定好,不要经常变动)
- 第二步:操作表结构中得数据,以达到实现业务得逻辑目的
例如:现在要实现一个用户管理系统
首先,我直接在MySQL自带得客户端创建相关得数据库和表结构(相当于,先创建好文件夹和Excel表以及表头等结构等)
create database userdb default character set utf8 collate utf8_general_ci;
create table users (
id int not null auto_increment primary key,
name varchar(32),
password varchar(64)
)default charset=utf8;
再在程序中编写一个简单得注册和登录函数
import pymysql
def register():
print("用户注册")
user = input("请输入用户名:")
password = input("请输入密码:")
# 1. 连接数据库
conn = pymysql.connect(host='localhost', user='root', password='密码', charset='utf8mb4')
cursor = conn.cursor()
# 2. 执行SQL语句(有注入风险,后续讲解)
sql = "INSERT INTO userbd (name, password) VALUES ("{}","{}")".format(user ,password )
cursor.execute(sql)
conn.commit()
# 关闭数据库连接
cursor.close()
conn.close()
print("注册成功,用户名是:{},密码是:{}".format(user ,password ))
def login():
print("用户登录:")
user = input("请输入用户名:")
password = input("请输入密码:")
# 1. 连接数据库
conn = pymysql.connect(host='localhost', user='root', password='密码', charset='utf8mb4')
cursor = conn.cursor()
# 2. 执行SQL语句(有注入风险,后续讲解)
sql = "select * from users where name='{}' and password='{}'".format(user ,password )
cursor.execute(sql)
#获取mysql查询得结果
result = cursor.fetchone()
# 关闭数据库连接
cursor.close()
conn.close()
if result:
print("登录成功:",result )
else:
print("登录失败")
def run():
choice = input("1.注册 2.登录")
if choice == '1':
register()
elif: choice == '2':
login()
else:
print("输入错误")
# 使用示例
if __name__ == "__main__":
run()
问题风险:
但是像前面的写法存在一定的风险
import pymysql
# 输入用户名和密码
user = input("请输入用户名:") # or 1=1 --
password = input("请输入密码:") # 123
# 1. 连接数据库
conn = pymysql.connect(host='localhost', user='root', password='密码', charset='utf8mb4')
cursor = conn.cursor()
# 2. 执行SQL语句(有注入风险,后续讲解)
# sql = "select * from users where name='张三' and password='123'"
# sql = "select * from users where name='' or 1=1 --and password='123'"
sql = "select * from users where name='{}' and password='{}'".format(user ,password )
cursor.execute(sql)
#获取mysql查询得结果
result = cursor.fetchone()
# 关闭数据库连接
cursor.close()
conn.close()
当用户输入user时,输入了 : or 1=1 --
,这样,即使用户不输入密码也能通过验证
select* from users where username='$user' AND password='$pass'
攻击者输入:
- 用户名:
admin' or 1=1 --
- 密码:任意值
生成的SQL变为:
SELECT * FROM users WHERE username='admin' or 1=1 -- ' AND password='anything'
关键破坏点:
1. 单引号闭合:'
提前结束了用户名字符串
2. or逻辑注入:or 1=1
使WHERE条件永远为真
3. 注释符:--
注释掉原SQL的剩余部分
其他潜在风险
- 即使不考虑
or 1=1
,简单的引号注入也会导致:-- 破坏查询语法导致错误 SELECT * FROM users WHERE name=''' AND password='' -- 二次查询攻击(如果支持多语句) SELECT * FROM users WHERE name=''; DROP TABLE users -- ' AND password=''
那么该如何避免这种注入呢?
切记,在SQL语句不要在使用Python的字符串格式化,而且使用pymysql的execute方法
import pymysql
# 输入用户名和密码
user = input("请输入用户名:") # or 1=1 --
password = input("请输入密码:") # 123
# 1. 连接数据库
conn = pymysql.connect(host='localhost', user='root', password='密码', charset='utf8mb4')
cursor = conn.cursor()
# cursor.execute("select * from users where name= %s and password=%s",{user ,password })
#或
cursor.execute("select * from users where name= %{n1}s and password=%{n2}s",{"n1":user ,"n2":password })
#获取mysql查询得结果
result = cursor.fetchone()
# 关闭数据库连接
cursor.close()
conn.close()
案例:Flask前端整合+MySQL
用户注册+用户信息展示
-
项目目录如下所示:
-
注册页面html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>添加用户</h1> <form action="/add/user" method="post"> <input type="text" name="user" placeholder="用户名" > <input type="text" name="pwd" placeholder="请输入密码"> <input type="text" name="mobile" placeholder="请输入手机号"> <input type="submit" value="提 交"> </form> </body> </html>
-
展示用户信息页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/plugins/bootstrap-3.4.1-dist/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/plugins/font-awesome-4.7.0/css/font-awesome.css"> <link rel="stylesheet" href="/static/plugins/bootstrap-datetimepicker-master/css/bootstrap-datetimepicker.css"> </head> <body> <div class="container"> <h1>用户列表</h1> <table class="table table table-bordered"> <thead> <tr> <th>ID</th> <th>姓名</th> <th>密码</th> <th>手机号</th> </tr> </thead> <tbody> {% for user in datalist %} <tr> <td>{{ user.id }}</td> <td>{{ user.username }}</td> <td>{{ user.password }}</td> <td>{{ user.mobile }}</td> </tr> {% endfor %} </tbody> </table> </div> <script src="/static/js/jquery.js"></script> <script src="/static/plugins/bootstrap-3.4.1-dist/js/bootstrap.js"></script> <script src="/static/plugins/bootstrap-datetimepicker-master/js/bootstrap-datetimepicker.js"></script> <script src="/static/plugins/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.zh-CN.js"></script> </body> </html>
-
python代码
from flask import Flask,render_template,request import pymysql app = Flask(__name__) def linkdb(name,pwd,mobile): #1. 连接数据库 conn = pymysql.connect(host='127.0.0.1', user='root', password='自己数据库密码', database='userlist', port=3306, charset='utf8') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 2. 发送指令 sql = "insert into info(username, password,mobile) values(%s, %s,%s)" cursor.execute(sql,[name ,pwd, mobile]) conn.commit() #3.关闭 cursor.close() conn.close() return "添加成功" @app.route('/add/user',methods=['GET', 'POST']) def add_user(): if request.method == 'GET': return render_template("add_user.html") print(request.form) username = request.form.get('user') pwd = request.form.get('pwd') mobile = request.form.get('mobile') ret = linkdb(username, pwd, mobile) print(ret) return '添加成功' @app.route('/show/user') def show_user(): # 从数据库获取所有的用户信息 conn = pymysql.connect(host='127.0.0.1', user='root', password='自己数据库密码', database='userlist', port=3306, charset='utf8') cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = "select * from info" cursor.execute(sql) datalist = cursor.fetchall() #3.关闭 cursor.close() conn.close() print(datalist) return render_template("show_user.html", datalist=datalist) if __name__ == '__main__': app.run(host='127.0.0.1', port=8000)
-
运行结果:
注册界面
提交成功
返回数据库客户端验证数据是否已经添加
用户信息展示:加上了BootStrap
样式