如何在 Python 中的 SQL 语句中使用变量?

2024-11-18 08:41:00
admin
原创
162
摘要:问题描述:我有以下 Python 代码:cursor.execute("INSERT INTO table VALUES var1, var2, var3,") 其中var1是整数,var2和var3是字符串。我怎样才能写出变量名称而不让 Python 将它们作为查询文本的一部分?解决方案...

问题描述:

我有以下 Python 代码:

cursor.execute("INSERT INTO table VALUES var1, var2, var3,")

其中var1是整数,var2var3是字符串。

我怎样才能写出变量名称而不让 Python 将它们作为查询文本的一部分?


解决方案 1:

cursor.execute("INSERT INTO table VALUES (%s, %s, %s)", (var1, var2, var3))

请注意,参数以元组形式传递。(a, b, c)如果传递单个参数,则元组需要以逗号结尾(a,)

数据库 API 会对变量进行正确的转义和引用。请注意不要使用字符串格式化运算符 ( %),因为

  1. 它不进行任何转义或引用。

  2. 它容易受到不受控制的字符串格式攻击,例如SQL 注入。

解决方案 2:

Python DB-API 的不同实现可以使用不同的占位符,因此您需要找出您正在使用哪一个 - 它可能是(例如使用 MySQLdb):

cursor.execute("INSERT INTO table VALUES (%s, %s, %s)", (var1, var2, var3))

或者(例如使用 Python 标准库中的 sqlite3):

cursor.execute("INSERT INTO table VALUES (?, ?, ?)", (var1, var2, var3))

或者其他(在VALUES您拥有(:1, :2, :3)、 或“命名样式”(:fee, :fie, :fo)(%(fee)s, %(fie)s, %(fo)s)将 dict 而不是 map 作为 的第二个参数传递给之后execute)。检查您正在使用的 DB API 模块中的字符串常量,并在http://www.python.org/dev/peps/pep-0249/paramstyle上查找 paramstyle以查看所有参数传递样式!

解决方案 3:

方法有很多。在实际代码中不要使用最明显的方法 ( %sw​​ith %),它容易受到攻击。

这里从 sqlite3 的 pydoc复制粘贴:

... 小心使用 Python 的字符串操作来组装查询,因为它们容易受到SQL 注入攻击。例如,攻击者可以简单地关闭单引号并注入 OR TRUE 来选择所有行:

# Never do this -- insecure!
symbol = input()

sql = "SELECT * FROM stocks WHERE symbol = '%s'" % symbol
print(sql)

cur.execute(sql)

如果你需要更多示例:

# Multiple values single statement/execution
c.execute('SELECT * FROM stocks WHERE symbol=? OR symbol=?', ('RHAT', 'MSO'))
print c.fetchall()
c.execute('SELECT * FROM stocks WHERE symbol IN (?, ?)', ('RHAT', 'MSO'))
print c.fetchall()
# This also works, though ones above are better as a habit as it's inline with syntax of executemany().. but your choice.
c.execute('SELECT * FROM stocks WHERE symbol=? OR symbol=?', 'RHAT', 'MSO')
print c.fetchall()
# Insert a single item
c.execute('INSERT INTO stocks VALUES (?,?,?,?,?)', ('2006-03-28', 'BUY', 'IBM', 1000, 45.00))

解决方案 4:

http://www.amk.ca/python/writing/DB-API.html

当您简单地将变量值附加到语句中时,请务必小心:想象一下用户命名自己';DROP TABLE Users;'——这就是为什么您需要使用 SQL 转义的原因,当您cursor.execute以得体的方式使用时,Python 会为您提供此功能。URL 中的示例为:

cursor.execute("insert into Attendees values (?, ?, ?)", (name, seminar, paid))

解决方案 5:

对于缺乏经验的 Python 用户来说,提供单一值的语法可能会令人困惑。

给定查询

INSERT INTO mytable (fruit) VALUES (%s)

一般来说*,传递给的值cursor.execute必须包装在有序序列中,例如元组或列表,即使值本身是单例,所以我们必须提供一个单元素元组,如下所示:(value,)

cursor.execute("""INSERT INTO mytable (fruit) VALUES (%s)""", ('apple',))

传递单个字符串

cursor.execute("""INSERT INTO mytable (fruit) VALUES (%s)""", ('apple'))

将导致错误,具体错误因 DB-API 连接器而异,例如

  • psycopg2:

TypeError:字符串格式化期间并非所有参数都已转换

  • sqlite3

sqlite3.ProgrammingError: 提供的绑定数量不正确。当前语句使用了 1 个,但提供了 5 个

  • mysql.连接器

mysql.connector.errors.ProgrammingError: 1064 (42000): 您的 SQL 语法有错误;


  • pymysql 连接器处理单个字符串参数时不会出错。但是,最好将字符串包装在元组中,即使它是一个单个的,因为

  • 如果你更换连接器包,则无需更改代码

  • 你保持一致的心理模型,即查询参数是一系列对象而不是单个对象。

解决方案 6:

这是一个非常老的问题,但这里还有更多细节。

不同的 DBMS 驱动程序实现不同的参数样式。您可以使用以下代码片段找出具体哪一种:

import sqlite3
print(sqlite3.paramstyle)           #   'qmark'
import pyodbc
print(pyodbc.paramstyle)            #   'qmark'
import mysql.connector
print(mysql.connector.paramstyle)   #   'pyformat'
import psycopg2
print(psycopg2.paramstyle)          #   'pyformat'
import oracledb
print(oracledb.paramstyle)          #   'named'

我已将我自己的测试结果纳入其中。

您可以从以下位置获取参数样式列表:

https://peps.python.org/pep-0249/#paramstyle

以下是摘录:

参数样式意义
数字数字、位置样式,例如… WHERE name=:1
命名命名样式,例如… WHERE name=:name
py格式Python 扩展格式代码,例如… WHERE name=%(name)s
佳标问号样式,例如… WHERE name=?
格式ANSI C printf 格式代码,例如… WHERE name=%s

之后,可以创建两个变量,一个用于 SQL,一个用于参数:

sql = 'INSERT INTO table VALUES ?,?,?'
data = (var1, var2, var3)
cursor.execute(sql, data)

这里,我使用了qmark样式。这data是一个值的元组,但它本来可以是一个列表。重点是,即使只有一个值,您也需要创建一个元组或列表。

如果您的 DBMS 使用pyformatnamed样式,则可以使用如下内容:

sql = 'INSERT INTO table VALUES %(first)s,%(second)s,%(third)s' #   pyformat
sql = 'INSERT INTO table VALUES :first,:second,:third'          #   named
data = {'first': var1, 'second': var2, 'third': var3}
cursor.execute(sql, data)

这里您使用一个字典,其中的键与 SQL 中使用的任意名称匹配。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用