8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

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

KidSudi 1月前

60 0

我有以下 Python 代码:cursor.execute(\'INSERT INTO table VALUES var1, var2, var3,\')其中 var1 是整数,var2 和 var3 是字符串。我怎样才能用 ...

我有以下 Python 代码:

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

其中 var1 是整数, var2 var3 是字符串。

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

帖子版权声明 1、本帖标题:如何在 Python 中的 SQL 语句中使用变量?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由KidSudi在本站《sqlite》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 这是一个非常老的问题,但这里还有更多细节。

    不同的 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 使用 pyf或mat or named 样式,则可以使用如下内容:

    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 中使用的任意名称匹配。

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

    给定查询

    INSERT INTO mytable (fruit) VALUES (%s)
    

    即使值本身是单例, curs元组.execute 传递的值 tuple or list 列表 (value,) .

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

    传递单个字符串

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

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

    • psycopg2:

      p5

    • sqlite3

      p6

    • mysql.连接器

      p7


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

    • 如果你更换连接器包,则无需更改代码
    • 你保持一致的心理模型,即查询参数是一系列对象而不是单个对象。
  • 好吧,无论是 SQL 转义还是变量绑定,都取决于您的数据库服务器/DB-API 驱动程序的好坏。我见过一些现实世界中广泛部署的生产数据库,它们的 DB-API 驱动程序只是进行转义,而不是将数据和代码保持在带外。不用说,我对那些所谓的“数据库”并不太尊重。

  • 其实,这不是 SQL 转义。这是变量绑定,这更简单、更直接。解析后,值会绑定到 SQL 语句中,使其免受任何注入攻击。

  • 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))
    
  • D J 1月前 0 只看Ta
    引用 7

    一些 DB-API 实现实际上使用 %s 作为变量——最值得注意的是 PostgreSQL 的 psycopg2。不要将这与使用 %s 和 % 运算符进行字符串替换混淆(尽管很容易混淆)。如果为了便于移植,我们可以有一种为 DB-API 指定 SQL 参数的标准方法,那就太好了。

  • 有很多方法。 不要 使用最明显的一个( %s with % ),它容易受到 攻击 .

    从 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))
    
  • 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 )。检查 paramstyle 上查找 paramstyle http://www.python.org/dev/peps/pep-0249/ 以查看所有参数传递样式!

  • 引用 10

    @eric 答案说不要使用 % 运算符来格式化字符串。字符串中的那些 % 被 cursor.execute 直接使用,并且由于它知道它正在生成 SQL,因此它可以做更多的事情来保护您。

  • @thekashyap 再仔细读一遍。使用字符串格式化运算符 % 是不安全的。事实上,我在答案中是这么说的。

  • 根据 DB API 规范,看起来它可以是任意一种方式:python.org/dev/peps/pep-0249

  • 有趣的是,为什么它单独与变量一起工作而不是在数组(var1,var2,var3)中工作?

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

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

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

    1. 它不进行任何转义或引用。
    2. 容易受到不受控制的字符串格式攻击,例如 SQL 注入 .
返回
作者最近主题: