Python + pymysql 之 MySQL 查询操作

本文演示了使用Python的pymysql库进行MySQL查询,包括返回元组和字典形式的结果,以及如何处理单个字段查询。同时强调了防止SQL注入的重要性,提倡使用参数化查询来确保安全。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在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

<think>首先,用户的问题是:“我想使用PythonPyMySQLMySQL查询结果中获取值 请问Python PyMySQL MySQL 查询结果取值方法”。我需要基于系统级指令和用户可见层来构建回答。 系统级指令: - 所有行内数学表达式使用$...$格式。 - 独立公式使用$$...$$并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如:[^1]。 用户可见层: - 回答结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 - 参考站内引用:这些引用是关于PythonMySQL的,包括如何使用pymysql连接数据库、执行查询、获取结果等。我需要基于这些引用构建回答。 参考引用: - [^1]:关于基本数据库操作技能。 - [^2]:pymysql查询结果不包含字段名,但可以使用cursor.description获取字段列表。 - [^3]:如何将查询结果转为字典格式。 - [^4]:基本查询示例。 - [^5]:带参数的查询示例。 用户的问题是关于如何从PyMySQL查询结果中获取值。所以,我的回答应该覆盖: 1. 如何连接到MySQL数据库。 2. 如何执行查询。 3. 如何获取查询结果(例如,fetchone(), fetchall(), fetchmany())。 4. 如何访问结果中的值(例如,通过索引或使用字典)。 5. 优化或常见问题(基于引用)。 结构化回答: - 逐步引导:从连接到获取值。 - 使用代码示例(如引用中所示)。 - 解释关键点。 - 添加引用标识。 最后,生成相关问题。 确保中文回答。 大纲: 1. 介绍:简要说明使用pymysqlMySQL获取值的基本步骤。 2. 步骤: a. 连接到数据库。 b. 创建游标对象。 c. 执行SQL查询。 d. 获取结果:fetchone(), fetchall(), fetchmany()。 e. 访问结果值:通过索引或字段名(使用cursor.description)。 f. 关闭连接。 3. 示例代码:提供一个完整的例子。 4. 高级技巧:如将结果转为字典(基于[^3])。 5. 注意事项:如错误处理、关闭连接。 6. 生成相关问题。 添加引用: - 在解释时,自然地添加引用标识。例如,当提到cursor.description时,引用[^2];当提到结果转字典时,引用[^3]。 数学表达式:用户问题不涉及数学,所以可能不需要。但如果提到索引或位置,可以用行内数学如$index$,但保持简单。 相关问题: - 基于用户问题,生成3-5个相关问题。例如: 1. 如何优化PyMySQL查询性能? 2. 如何处理查询结果中的空值? 3. 如何执行带参数的查询以防止SQL注入? 4. PyMySQL与其他MySQL库的比较? 5. 如何将查询结果保存到文件? 最终回答结构: - 清晰标题或部分。 - 代码块使用Markdown格式。 - 结尾添加相关问题。</think>### Python PyMySQL MySQL 查询结果取值方法详解 使用PythonPyMySQLMySQL查询结果中获取值,是数据库操作的核心技能。PyMySQL提供了灵活的游标方法,支持多种数据获取方式。以下是结构化步骤和示例,确保您能高效处理查询结果。所有方法均基于PyMySQL官方文档和最佳实践[^1]。 #### 步骤1: 连接到MySQL数据库 首先,建立数据库连接。需要指定主机、用户、密码和数据库名。使用`pymysql.connect()`创建连接对象,并通过`cursor()`获取游标对象。游标用于执行SQL和获取结果。 ```python import pymysql # 建立数据库连接 db = pymysql.connect( host="localhost", # 替换为您的MySQL主机 user="root", # 用户名 password="your_password", # 密码 database="test_db" # 数据库名 ) cursor = db.cursor() # 创建游标对象 ``` #### 步骤2: 执行SQL查询 使用游标的`execute()`方法执行SQL语句。支持静态查询或带参数的动态查询(防止SQL注入)[^5]。 ```python # 静态查询示例 sql = "SELECT id, name, age FROM users WHERE age > 18" cursor.execute(sql) # 带参数查询示例(推荐) sql_param = "SELECT * FROM users WHERE name = %s" cursor.execute(sql_param, ("张三",)) # 参数作为元组传递 ``` #### 步骤3: 获取查询结果 PyMySQL提供三种主要方法获取结果: - **`fetchone()`**: 获取下一行结果,返回元组(如`(1, '张三', 25)`)。适合逐行处理[^4]。 - **`fetchall()`**: 获取所有行,返回元组列表(如`[(1, '张三', 25), (2, '李四', 30)]`)。适合小数据集[^2]。 - **`fetchmany(size)`**: 获取指定行数(如`size=5`),返回部分结果集。适合大数据集分页。 示例代码: ```python # 获取单行 row = cursor.fetchone() print("单行结果:", row) # 输出: (1, '张三', 25) # 获取所有行 all_rows = cursor.fetchall() print("所有行结果:", all_rows) # 输出: [(1, '张三', 25), (2, '李四', 30)] # 获取多行(例如5行) some_rows = cursor.fetchmany(5) ``` #### 步骤4: 访问结果值 查询结果默认以元组形式返回,可通过索引或字段名访问值: - **索引访问**: 直接使用位置索引(从0开始),例如`row[0]`获取第一列。 - **字段名访问**: 需结合`cursor.description`获取字段列表。`cursor.description`返回字段元信息(如字段名、类型),可通过字段名映射索引[^2][^3]。 ```python # 索引访问示例 if row: print("ID:", row[0], "姓名:", row[1]) # 输出: ID: 1 姓名: 张三 # 字段名访问示例(推荐) # 获取字段名与索引的映射 field_index = {desc[0]: index for index, desc in enumerate(cursor.description)} print("字段映射:", field_index) # 输出: {'id': 0, 'name': 1, 'age': 2} # 通过字段名取值 if row: user_id = row[field_index['id']] user_name = row[field_index['name']] print(f"用户ID: {user_id}, 姓名: {user_name}") # 输出: 用户ID: 1, 姓名: 张三 ``` #### 步骤5: 将结果转为字典(高级技巧) 为提高可读性,可将元组结果转为字典格式(键为字段名,值为数据)。定义一个辅助函数: ```python def result_to_dict(cursor): """将查询结果转为字典列表[^3]""" columns = [desc[0] for desc in cursor.description] # 获取字段名列表 return [dict(zip(columns, row)) for row in cursor.fetchall()] # 使用示例 cursor.execute("SELECT id, name FROM users") dict_result = result_to_dict(cursor) print(dict_result) # 输出: [{'id': 1, 'name': '张三'}, {'id': 2, 'name': '李四'}] ``` #### 步骤6: 关闭连接 操作完成后,必须关闭游标和连接以释放资源[^1]。 ```python cursor.close() # 关闭游标 db.close() # 关闭数据库连接 ``` #### 完整示例 ```python import pymysql try: # 连接数据库 db = pymysql.connect(host="localhost", user="root", password="123456", database="test_db") cursor = db.cursor() # 执行带参数查询 cursor.execute("SELECT * FROM users WHERE age > %s", (18,)) # 获取结果并转为字典 def result_to_dict(cursor): columns = [desc[0] for desc in cursor.description] return [dict(zip(columns, row)) for row in cursor.fetchall()] users = result_to_dict(cursor) for user in users: print(f"用户: {user['name']}, 年龄: {user['age']}") finally: cursor.close() db.close() ``` #### 注意事项 - **错误处理**: 使用`try-except`捕获异常(如`pymysql.Error`),避免程序崩溃。 - **性能优化**: 大数据集时优先使用`fetchmany()`,避免内存溢出。 - **字段名大小写**: MySQL字段名默认不区分大小写,但Python字典键区分大小写[^3]。 - **资源释放**: 确保在`finally`块中关闭连接,防止资源泄漏[^1]。 通过以上步骤,您可灵活获取并处理MySQL查询结果。实际应用中,结合参数化查询和字典转换能提升代码可维护性和安全性[^3][^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值