
本文详细介绍了在python中使用`psycopg2`库与postgresql数据库交互时,如何安全有效地将python变量嵌入到sql查询语句中。通过避免直接字符串拼接,我们将重点讲解使用sql占位符(`%s`)和`execute()`方法的参数化查询机制,这不仅能解决常见的`typeerror`,更能有效防范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免费学习笔记(深入)”;
即使我们尝试通过Python的f-string或字符串连接来直接构建SQL,例如 cur.execute(f"SELECT password FROM user WHERE email = '{inputed_email}';"),虽然解决了参数数量的问题,但这是一种非常危险的做法,因为它容易受到SQL注入攻击。
psycopg2(以及大多数Python数据库API)提供了一种安全且推荐的方式来处理变量:参数化查询。其核心思想是在SQL语句中使用占位符,然后将变量的值作为单独的参数传递给execute()方法。psycopg2会负责正确地转义这些值,防止SQL注入。
Picit AI
免费AI图片编辑器、滤镜与设计工具
195
查看详情
对于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("数据库连接已关闭。")关键点解释:
如果查询中需要使用多个变量,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("数据库连接已关闭。")在Python中使用psycopg2执行PostgreSQL查询并嵌入变量时,核心原则是采用参数化查询。通过在SQL语句中使用%s占位符,并将变量值作为execute()方法的第二个参数(一个列表或元组)传递,我们不仅能避免TypeError等常见错误,更能有效地防止SQL注入攻击,从而编写出更安全、更健壮的数据库交互代码。遵循这些最佳实践,将大大提高您Python数据库应用的可靠性。
以上就是如何在Python中安全地使用变量执行PostgreSQL查询的详细内容,更多请关注其它相关文章!
相关文章:
c++如何使用折叠表达式(Fold Expressions)_c++17可变参数模板新技巧
顺丰快递查单号物流信息 顺丰快递小程序查询入口
在J*a里如何理解依赖关系的方向_依赖方向在模块结构中的作用
解决J*aScript中重复选择项的确认对话框显示问题
PDF怎么合并PDF并保持格式_PDF合并文件保持排版教程
MinIO大规模对象列表性能瓶颈深度解析与外部元数据管理策略
文本文档写html代码怎么运行_文本文档html代码运行步骤【教程】
Composer中的^和~符号代表什么_精通Composer版本号语义化约束
Golang如何实现微服务鉴权与权限控制_Golang微服务鉴权与权限管理实践
在FastAPI中利用lifespan与依赖注入高效管理Redis连接池
iwriter统一登录平台 iwrite账号密码登录页面
Flexbox布局实践:实现粘性导航栏与底部固定页脚
CSS Grid如何控制元素对齐_align-items与justify-items组合使用
C++ vector二维数组定义_C++ vector of vector用法
Lar*el Excel导入时生成自定义递增ID的策略与实践
聚水潭ERP登录页面入口 聚水潭ERP官网登录界面
AO3官方镜像站点汇总 AO3同人作品网页版直达链接
J*aScript类型检查_j*ascript代码规范
俄罗斯Yandex免登录入口_Yandex搜索引擎官网一键直达
qq游戏免费畅玩入口_qq游戏电脑版快速启动
基于多条件高效更新SQL表:利用CASE表达式优化业务逻辑
动漫岛观看全网网 动漫岛在线正版动漫入口
怎么在mac上运行html代码_mac运行html代码方法【指南】
中兴BladeV30怎样用测距估书架层高_iPhone中兴BladeV30测距估书架层高【家装参考】
邮政快递包裹最新位置 邮政快递实时追踪入口
Go语言中JSON数据解码与字段访问指南
如何使用Rector自动化升级旧代码_通过Composer安装和配置Rector进行代码重构
浏览器打开即用 美图秀秀网页版入口
新手怎么开始学化妆 零基础化妆入门教程
React中useState与局部变量:理解组件状态管理与渲染机制
composer 和 npm/yarn 在管理依赖方面有什么核心思想差异?
J*aScript map 方法中处理循环元素为空数组的策略
黑鲨3Pro怎样在相册开漫画风滤镜_iPhone黑鲨3Pro相册开漫画风滤镜【趣味滤镜】
魅族20怎样在浏览器开无图省流_iPhone魅族20浏览器开无图省流【流量节省】
微博网页版官方账号登录 微博网页版内容浏览使用指南
C++如何操作注册表_Windows平台下C++读写注册表的API函数详解
蓝湖怎样用切图标注提对接效率_蓝湖用切图标注提对接效率【设计对接】
J*aScript实现动态背景色下的文本与按钮颜色自适应调整
苹果手机如何防止被恶意App追踪
Excel Power Pivot如何处理XML数据源 构建高级数据模型
星露谷物语官网入口 星露谷物语游戏官网入口
怎么在html里运行vbs脚本_html中运行vbs脚本方法【教程】
限制HTML日期输入框的日期选择范围
sublime怎么进行远程开发编辑_配置rsub/rmate实现sublime编辑服务器文件
AO3访问入口汇总 AO3网页版同人作品一键直达
如何设置Windows Defender的定时扫描_计划任务实现自动杀毒【安全】
J*aScript教程:根据元素文本内容动态设置背景色
CSS实现侧边栏导航项全宽圆角悬停背景效果
PHP教程:高效从URL路径中提取倒数第二个片段
ArrayList与LinkedList操作复杂度详解:遍历与修改