代码之家  ›  专栏  ›  技术社区  ›  John Giotta iaforek

将参数传递到db.execute for where in…int list

  •  10
  • John Giotta iaforek  · 技术社区  · 16 年前

    使用python的db api规范,可以将参数参数参数传递给execute()方法。我的语句的一部分是WHEREIN子句,我一直在使用元组填充IN。例如:

    params = ((3, 2, 1), )
    stmt = "SELECT * FROM table WHERE id IN %s"
    db.execute(stmt, params)
    

    但是当我遇到参数tuple仅为1项的tuple的情况时,执行失败。

    ProgrammingError:错误:语法错误在或接近”)。
    第13行:其中id在(3,)

    如何使元组正确地与子句一起使用?

    4 回复  |  直到 9 年前
        1
  •  12
  •   mechanical_meat nazca    10 年前

    编辑:请注意,正如@rspeer在评论中所提到的,要采取预防措施来保护自己免受SQL注入攻击。

    测试用 pg8000 (与PostgreSQL数据库引擎兼容的DB-API 2.0纯python接口):

    这是将多个参数传递给“in”子句的推荐方法。

    params = [3,2,1]
    stmt = 'SELECT * FROM table WHERE id IN (%s)' % ','.join('%s' for i in params)
    cursor.execute(stmt, params)
    

    另一个编辑(完全测试和工作示例):

    >>> from pg8000 import DBAPI
    >>> conn = DBAPI.connect(user="a", database="d", host="localhost", password="p")
    >>> c = conn.cursor()
    >>> prms = [1,2,3]
    >>> stmt = 'SELECT * FROM table WHERE id IN (%s)' % ','.join('%s' for i in prms)
    >>> c.execute(stmt,prms)
    >>> c.fetchall()
    ((1, u'myitem1'), (2, u'myitem2'), (3, u'myitem3'))
    
        2
  •  1
  •   Daniel    16 年前

    错误来自3后面的逗号。只需为单个值保留它,就可以设置。

    params = ((3), ... )
    stmt = "SELECT * FROM table WHERE id IN %s"
    db.execute(stmt, params)
    
        3
  •  1
  •   rspeer    10 年前

    这也许不是你问的问题的确切答案,但我认为它可以解决你的问题。

    python的db-api似乎没有给您一种将元组作为安全替换参数传递的方法。伯尼接受的答案是使用python % 替换运算符,这是不安全的。

    但是,您可能不必将元组作为参数传递,特别是当您想要的元组是另一个SQL查询的结果时(如您向Daniel指出的那样)。相反,您可以使用SQL子查询。

    如果在IN子句中需要的ID集是 SELECT id FROM other_table WHERE use=true ,例如:

    stmt = "SELECT * FROM table WHERE id IN (SELECT id FROM other_table WHERE use=true)"
    db.execute(stmt)
    

    这也可以参数化(安全方式)。如果要选择的ID是具有给定 parent_id :

    stmt = "SELECT * FROM table WHERE id IN (SELECT id FROM other_table WHERE parent_id=%s)"
    params = (parent_id,)
    db.execute(stmt, params)
    
        4
  •  0
  •   kielni    9 年前

    接受的答案有SQL注入的风险;您永远不应该将用户输入直接传递到数据库。相反,使用正确数量的占位符生成一个查询,然后让pg8000进行转义:

    params = [3,2,1]
    # SELECT * from table where id in (%s,%s,%s)
    stmt = 'SELECT * FROM table WHERE id IN ({})'.format(','.join(['%s']*len(params)))
    cursor.execute(stmt, tuple(params))