在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()
打印输出结果:
<class 'tuple'>
(1, '张三', '2233445566', 18)从中可以看出,默认情况下,查询结果返回的是元组tuple形式
返回元组会有一个问题,当你只查询一个属性字段时,返回的结果会是有逗号的元组
例如:sql改变一下
    sql = """
    select name from student_info where id =2;
    """此时,打印输出结果:
<class 'tuple'>
('李四',)此时,建议return前,简单处理一下,我们只取返回结果元组的第一个元素
student = cursor.fetchone()[0]此时,打印输出结果:
<class 'str'>
李四这样一来,函数的输出结果就可以直接使用啦
那么,还有没有其他返回形式呢,答案是有的
还可以返回字典形式,在代码中创建游标时,传入参数,指定返回字典形式
cursor = db.cursor(pymysql.cursors.DictCursor)此时,打印输出结果:
<class 'dict'>
{'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


















