如何在Python中安全地使用变量执行PostgreSQL查询


如何在Python中安全地使用变量执行PostgreSQL查询

本文详细介绍了在python中使用`psycopg2`库与postgresql数据库交互时,如何安全有效地将python变量嵌入到sql查询语句中。通过避免直接字符串拼接,我们将重点讲解使用sql占位符(`%s`)和`execute()`方法的参数化查询机制,这不仅能解决常见的`typeerror`,更能有效防范sql注入攻击,提升代码的健壮性和安全性。

引言:在Python中执行带变量的SQL查询

在开发数据库驱动的Python应用时,经常需要根据程序运行时的数据动态构建SQL查询。例如,根据用户输入查询特定记录,或者更新某个字段的值。初学者常犯的一个错误是直接将Python变量拼接到SQL字符串中,这不仅可能导致语法错误或运行时异常,更重要的是,它会为SQL注入攻击打开大门,严重威胁应用程序的安全性。

本教程将以psycopg2库为例,演示如何在Python中正确且安全地使用变量执行PostgreSQL查询。

错误的实践:直接拼接变量

让我们首先看看一个常见的错误示例。假设我们想根据一个Python变量inputed_email查询用户的密码:

import psycopg2

inputed_email = "test@example.com" # 假设这是从用户输入获取的变量

conn = None
cur = None
try:
    conn = psycopg2.connect("dbname=postgres user=postgres password=postgres")
    cur = conn.cursor()

    # 错误的用法:直接将变量作为execute的独立参数,或进行字符串拼接
    # cur.execute("SELECT password FROM user WHERE email = ", inputed_email, ";")
    # 这种方式会导致 TypeError: function takes at most 2 arguments (3 given)
    # 即使使用字符串拼接,如 f"SELECT password FROM user WHERE email = '{inputed_email}';"
    # 也存在SQL注入风险且易出错

    print("尝试执行查询...")
    # 假设这里是错误的代码,为了演示问题,我们不会运行它
    # cur.execute("SELECT password FROM user WHERE email = ",inputed_email,";")
    # print(cur.fetchone())

except TypeError as e:
    print(f"捕获到错误: {e}")
    print("错误提示:execute() 函数最多接受两个参数,但您提供了三个。")
except Exception as e:
    print(f"发生其他错误: {e}")
finally:
    if cur:
        cur.close()
    if conn:
        conn.close()
    print("数据库连接已关闭。")

上述代码中,cur.execute("SELECT password FROM user WHERE email = ", inputed_email, ";") 尝试将SQL语句、变量和分号作为三个独立的参数传递给execute()函数。然而,psycopg2的execute()方法最多只接受两个参数:SQL查询字符串和可选的参数序列(用于占位符)。因此,这会导致TypeError: function takes at most 2 arguments (3 given)。

即使我们尝试通过Python的f-string或字符串连接来直接构建SQL,例如 cur.execute(f"SELECT password FROM user WHERE email = '{inputed_email}';"),虽然解决了参数数量的问题,但这是一种非常危险的做法,因为它容易受到SQL注入攻击。

正确的实践:使用占位符进行参数化查询

psycopg2(以及大多数Python数据库API)提供了一种安全且推荐的方式来处理变量:参数化查询。其核心思想是在SQL语句中使用占位符,然后将变量的值作为单独的参数传递给execute()方法。psycopg2会负责正确地转义这些值,防止SQL注入。

Notion Sites Notion Sites

Notion 推出的AI网站构建工具,允许用户将 Notion 页面直接发布为完整网站。

Notion Sites 246 查看详情 Notion Sites

对于psycopg2,标准的占位符是 %s。

单个变量的参数化查询

当查询中只有一个变量时,我们这样使用:

import psycopg2

inputed_email = "test@example.com" # 假设这是从用户输入获取的变量

conn = None
cur = None
try:
    conn = psycopg2.connect("dbname=postgres user=postgres password=postgres")
    cur = conn.cursor()

    # 正确的用法:使用 %s 占位符,并将变量作为 execute() 的第二个参数(一个列表或元组)
    sql_query = "SELECT password FROM public.user WHERE email = %s" # 注意:这里移除了末尾的分号,通常不是必需的
    cur.execute(sql_query, [inputed_email]) # 第二个参数必须是可迭代对象(如列表或元组)

    result = cur.fetchone()
    if result:
        print(f"找到用户密码: {result[0]}")
    else:
        print(f"未找到邮箱为 '{inputed_email}' 的用户。")

    conn.commit() # 对于SELECT语句通常不需要commit,但对于INSERT/UPDATE/DELETE是必需的

except psycopg2.Error as e:
    print(f"数据库操作错误: {e}")
    if conn:
        conn.rollback() # 发生错误时回滚事务
except Exception as e:
    print(f"发生其他错误: {e}")
finally:
    if cur:
        cur.close()
    if conn:
        conn.close()
    print("数据库连接已关闭。")

关键点解释:

  1. 占位符 %s: 在SQL查询字符串中,任何你想插入变量值的地方,都用 %s 代替。
  2. execute() 的第二个参数: execute() 方法的第二个参数必须是一个可迭代对象(如列表或元组),其中包含按顺序对应占位符的值。即使只有一个值,也必须将其放在列表或元组中,例如 [inputed_email]。

多个变量的参数化查询

如果查询中需要使用多个变量,execute() 方法的第二个参数就包含相应数量的变量,顺序与SQL语句中的 %s 占位符一致。

import psycopg2

user_email = "jane.doe@example.com"
user_lastname = "Doe"

conn = None
cur = None
try:
    conn = psycopg2.connect("dbname=postgres user=postgres password=postgres")
    cur = conn.cursor()

    # 多个变量的参数化查询
    sql_query = "SELECT firstname, password FROM public.user WHERE email = %s AND lastname = %s"
    cur.execute(sql_query, (user_email, user_lastname)) # 可以使用元组或列表

    result = cur.fetchone()
    if result:
        print(f"找到用户: {result[0]}, 密码: {result[1]}")
    else:
        print(f"未找到邮箱为 '{user_email}' 且姓氏为 '{user_lastname}' 的用户。")

    conn.commit()

except psycopg2.Error as e:
    print(f"数据库操作错误: {e}")
    if conn:
        conn.rollback()
except Exception as e:
    print(f"发生其他错误: {e}")
finally:
    if cur:
        cur.close()
    if conn:
        conn.close()
    print("数据库连接已关闭。")

注意事项与最佳实践

  1. SQL注入防护: 参数化查询是防止SQL注入攻击的黄金法则。psycopg2会自动转义传递给占位符的所有值,确保它们被视为数据而不是可执行的SQL代码。
  2. execute() 参数类型: 始终记住,execute() 的第二个参数必须是一个可迭代对象(列表或元组),即使只有一个变量。
  3. SQL语句末尾的分号: 在psycopg2中,SQL语句末尾的分号通常不是必需的,并且在某些情况下可能会导致问题。建议省略它,除非数据库要求或你正在执行多个语句。
  4. 事务管理: 对于INSERT、UPDATE、DELETE等修改数据的操作,务必在操作成功后调用 conn.commit() 来保存更改。如果发生错误,应调用 conn.rollback() 来撤销未提交的更改。对于SELECT操作,通常不需要commit。
  5. 资源管理: 始终确保在操作完成后关闭游标(cur.close())和数据库连接(conn.close()),以释放数据库资源。使用 try...except...finally 块是实现这一点的标准模式。
  6. 错误处理: 捕获psycopg2.Error异常可以更具体地处理数据库相关的错误。

总结

在Python中使用psycopg2执行PostgreSQL查询并嵌入变量时,核心原则是采用参数化查询。通过在SQL语句中使用%s占位符,并将变量值作为execute()方法的第二个参数(一个列表或元组)传递,我们不仅能避免TypeError等常见错误,更能有效地防止SQL注入攻击,从而编写出更安全、更健壮的数据库交互代码。遵循这些最佳实践,将大大提高您Python数据库应用的可靠性。

以上就是如何在Python中安全地使用变量执行PostgreSQL查询的详细内容,更多请关注其它相关文章!


# python  # 最多  # 这是  # 是一个  # 只有一个  # 迭代  # 文档  # 多个  # 可迭代对象  # 防止sql注入  # sql语句  # 邮箱  # sql注入  # ai  # word  # 第二个  # 网络营销和推广的计划书  # 渭南seo优化渠道  # 俄罗斯产品文案网站推广  # 私域网站怎么推广产品的  # 新乡短视频seo渠道  # 保定哪个网站推广好用  # seo优化方案魔呗  # 凤岗东莞网站建设  # 睡眠产品推广营销  # 苏州区网站建设  # 如何在  # 不需要 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894


相关推荐: 火狐浏览器无法自动更新怎么办 手动更新火狐浏览器到最新版本【解决】  我的世界游戏平台入口 我的世界官方官网直达链接  vivo云服务一直提示空间不足怎么办 怎么办vivo云服务老是提示空间不足  自定义你的VS Code状态栏,监控关键信息  4399造梦西游3无敌版_4399游戏入口  德邦快递会员怎么开通  豆包AI怎样为教育场景定制答疑逻辑_为教育场景定制豆包AI答疑逻辑方案【方案】  使用document.execCommand实现Web文本编辑器加粗/取消加粗  《随手记》备份数据方法  如何在CSS中使用absolute实现登录弹窗居中_transform translate结合  sublime如何配置PHP开发环境_在sublime中运行与调试PHP代码  管理打开的编辑器:固定、分组和关闭技巧  动漫岛汉化官网网 动漫岛官方动漫汉化地址  《海贝音乐》均衡器设置方法  解决CSS background 属性中 cover 关键字的常见误用  优化Flask模板中SQLAlchemy查询迭代标签:处理字符串空格问题  《小黑盒》删除历史浏览方法  如何在CSS中使用伪类选择器_hover实现悬停效果  视频号视频怎么免费保存到相册?保存到相册需要注意什么?  阿里旺旺电脑网页版入口 阿里旺旺电脑版网页登录入口  抖音号怎么解除企业认证改成个人?改成个人有影响吗?  CSS如何使用outline-offset与颜色组合突出元素边框  铁路12306怎么申请退票_铁路12306退票申请操作流程  PHP魔术方法__set与__isset:设计考量、性能权衡与静态分析的视角  《淘票票》添加到苹果钱包教程  Flask 应用中图片动态更新与上传:实现客户端定时刷新与服务器端文件管理  《全民k歌》音乐怎么下载到本地2025  Golang如何实现HTTP请求重试机制_Golang HTTP请求错误处理策略  C++ switch case字符串_C++如何实现字符串switch匹配  哔哩哔哩黑名单怎么查看  《oppo商城》维修服务位置  《爱笔思画x》涂色教程  mysql怎么导入sql文件_mysql导入sql文件的方法与技巧  《律学法考》查看学习数据方法  微信网页版在线登录 微信网页版在线使用入口  Firefox OS应用开发:解决XMLHttpRequest跨域请求阻塞问题  《虎扑》取消评分记录方法  OTT月报 | 2025年9月智能电视大数据报告  PHP安全加载非公开目录图片与动态内容类型处理指南  研招网官方网站正版登录网址_中国研究生招生信息网官网首页  C++ optional用法详解_C++17处理可能为空的返回值  《via浏览器》强制缩放网页设置方法  《气泡星球》兑换码礼包大全  word文档中的分隔符有哪些不同类型和用途_Word分隔符类型与用途方法  sublime怎么在文件中显示代码结构大纲_sublime符号列表功能  《红果免费短剧》下载观看方法  菜鸟裹裹怎样获得取件码_菜鸟裹裹获得取件码步骤  京东快递包裹信息查询入口 京东快递官方查询平台入口  优化2xN网格最大路径和的动态规划算法实践  《浙里办》电子发票开具方法 

 2025-12-12

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.