Python + pymysql 之 MySQL 查询操作

news/2024/11/9 20:45:26

在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


http://www.niftyadmin.cn/n/3656050.html

相关文章

RESTful GeoWeb学习手记(一):构建REST风格的网络服务

RESTful GeoWeb学习手记&#xff08;一&#xff09;&#xff1a;构建REST风格的网络服务粟卫民http://www.gisdev.cn/ http://blog.csdn.net/suen/ 日期&#xff1a;2007-8-14保留所有版权。如需转载&#xff0c;请联系作者&#xff0c;并在醒目位置注明出处GeoWeb是一个新造出…

bug减半、工资翻倍(1024)

祝所有程序员&#xff1a;“程”风破浪“序”怀若谷“员”见卓识“节”节高升“日”积月累“快”马加鞭“乐”在其中************************************************ bug减半 **********************************************************“程”风破浪 “序”怀若谷 “员…

RESTful GeoWeb学习手记(二):GeoWeb大会介绍

RESTful GeoWeb学习手记&#xff08;二&#xff09;&#xff1a;GeoWeb大会介绍粟卫民http://www.gisdev.cn/ http://blog.csdn.net/suen/ 日期&#xff1a;2007-9-19保留所有版权。如需转载&#xff0c;请联系作者&#xff0c;并在醒目位置注明出处GeoWeb大会&#xff08;http…

如何理解java的值传递?

1、基本数据类型&#xff08;值传递&#xff09; java中的基本数据类型可以在栈&#xff08;stack&#xff09;中直接分配内存&#xff0c;它有以下八种&#xff1a; boolean&#xff0c;byte&#xff0c;char&#xff0c;short&#xff0c;int&#xff0c;long&#xff0c;f…

GOOGLE地球浏览器分析(七):开发人员讲述的Google Earth真正工作原理

GOOGLE地球浏览器分析&#xff08;七&#xff09;&#xff1a;开发人员讲述的Google Earth真正工作原理粟卫民http://www.gisdev.cn/ http://blog.csdn.net/suen/ 日期&#xff1a;2007-07-09转载&#xff1a;http://www.realityprime.com/articles/how-google-earth-really-wo…

基于.NET 2.0的GIS开源项目SharpMap分析手记(十二):SharpMap WMS服务及其Openlayers访问

基于.NET 2.0的GIS开源项目SharpMap分析手记&#xff08;十二&#xff09;&#xff1a;SharpMap WMS服务及其Openlayers访问粟卫民 http://www.gisdev.cn/ http://blog.csdn.net/suen/ 日期&#xff1a;2007-7-12保留所有版权。如需转载&#xff0c;请联系作者&#xff0c;并在…

GOOGLE地球浏览器分析(五):KML文件基本格式

GOOGLE地球浏览器分析&#xff08;五&#xff09;&#xff1a;KML文件基本格式粟卫民http://www.gisdev.cn/ http://blog.csdn.net/suen/ 日期&#xff1a;2007-7-5保留所有版权。如需转载&#xff0c;请联系作者&#xff0c;并在醒目位置注明出处第三节我们介绍了KML文件的定义…

GOOGLE地球浏览器分析(六):AJAX支持的GOOGLE地图MASHUP教程

GOOGLE地球浏览器分析&#xff08;六&#xff09;&#xff1a;AJAX支持的GOOGLE地图MASHUP教程粟卫民http://www.gisdev.cn/ http://blog.csdn.net/suen/ 日期&#xff1a;2007-06-12转载&#xff1a;http://dev2dev.bea.com.cn/techdoc/2007/06/java-soa-google-mashups.html …