在MySQL中构建一个测试表,如下:
# -*- coding: UTF-8 -*-
import pymysql
def mysql_query():
"""
MySQL查询
:return:
"""
# 打开数据库连接
db = pymysql.connect(host="127.0.0.1",
user="root",
password="testtest",
database="testdb")
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = db.cursor()
# SQL语句
sql = """
select * from student_info;
"""
# 使用 execute() 方法执行 SQL 查询
cursor.execute(sql)
# 获取第一条结果
student = cursor.fetchone()
print(type(student))
print(student)
# 关闭数据库连接
db.close()
# 返回查询结果
return student
if __name__ == '__main__':
mysql_query()
打印输出结果:
(1, '张三', '2233445566', 18)
从中可以看出,默认情况下,查询结果返回的是元组tuple形式
返回元组会有一个问题,当你只查询一个属性字段时,返回的结果会是有逗号的元组
例如:sql改变一下
sql = """
select name from student_info where id =2;
"""
此时,打印输出结果:
('李四',)
此时,建议return前,简单处理一下,我们只取返回结果元组的第一个元素
student = cursor.fetchone()[0]
此时,打印输出结果:
李四
这样一来,函数的输出结果就可以直接使用啦
那么,还有没有其他返回形式呢,答案是有的
还可以返回字典形式,在代码中创建游标时,传入参数,指定返回字典形式
cursor = db.cursor(pymysql.cursors.DictCursor)
此时,打印输出结果:
{'name': '李四'}
把其中的
student = cursor.fetchone()
替换为
students = cursor.fetchall()
此时返回全部数据,默认为元组形式
((1, '张三', '2233445566', 18), (2, '李四', '12341234', 19), (3, '王五', '11112222', 20))
同样需要注意,如果只是查询一个属性字段的话,返回的是元组形式
(('张三',), ('李四',), ('王五',))
此时,可以用一个循环,来提取属性内容到
names = [student[0] for student in students]
此时,打印names结果为:
['张三', '李四', '王五']
例如:根据学生id查询学生姓名
传参的方式:
# SQL语句 sql = """ select name from student_info where id = %s; """ # 使用 execute() 方法执行 SQL 查询 cursor.execute(sql, [id])
注意:此处的占位符是%s,无论是字符串、数字或者其他类型,都是这个占位符。 %s不能加引号。
上代码
def get_name_by_id(id):
"""
根据学生id查询学生姓名
:param id:
:return:
"""
# 打开数据库连接
db = pymysql.connect(host="127.0.0.1",
user="root",
password="testtest",
database="testdb")
# 使用 cursor() 方法创建一个游标对象 cursor 以元组形式返回
cursor = db.cursor()
# SQL语句
sql = """
select name from student_info where id = %s;
"""
# 使用 execute() 方法执行 SQL 查询
cursor.execute(sql, [id])
# 获取第一条结果
name = cursor.fetchone()[0]
# 关闭数据库连接
db.close()
# 返回查询结果
return name
if __name__ == '__main__':
id = 3
name = get_name_by_id(id)
print(name)
返回打印结果:
王五
为什么不用拼接字符串的方式来组装sql语句呢?
为了防注入,建议大家养成习惯
拿一个典型的登录注入来举例:
username = 'zhangsan'
password = '123456'
sql = "SELECT user_id FROM users WHERE username = '{}' AND password = '{}';".format(username, password)
看起来也没毛病,但是如果此时,username传入的是如下内容:
username = 'zhangsan OR 1 = 1 -- a'
sql就会变成这个样子了:
SELECT user_id FROM users WHERE username = 'zhangsan OR 1 = 1 -- a' AND password = '123456';
美化一下SQL
SELECT
user_id
FROM
users
WHERE
username = 'zhangsan'
OR 1 = 1 -- a AND password = 'abc';
这段sql的效果是无论输入什么密码,都会返回登录成功。
改成使用pymysql列表方式传参就不怕注入啦
def get_user_id(username, password):
# 打开数据库连接
db = pymysql.connect(host="127.0.0.1",
user="root",
password="testtest",
database="testdb")
# 使用 cursor() 方法创建一个游标对象 cursor 以元组形式返回
cursor = db.cursor()
# SQL语句
sql = """
SELECT user_id FROM users WHERE username = %s AND password = %s;
"""
# 使用 execute() 方法执行 SQL 查询
cursor.execute(sql, [username, password])
# 获取第一条结果
user_id = cursor.fetchone()
# 关闭数据库连接
db.close()
# 返回查询结果
return user_id
if __name__ == '__main__':
username = 'zhangsan OR 1 = 1 -- a'
password = 'abc'
user_id = get_user_id(username, password)
print(bool(user_id))
返回打印结果为:
False