【问题标题】:How to write this query?如何编写这个查询?
【发布时间】:2011-03-21 23:32:49
【问题描述】:

假设我有一个这样的 sqlite 表:

Id|B|C|D

我有一个包含Id 的一些值的列表。也许 [1,3,45,67](类似的东西。)

我想获取列表中具有 ID 的行,其 B 值大于 5,并最终按 C 排序。

我觉得我给这个的标题很糟糕,如果你能想到更好的,请编辑它。

【问题讨论】:

    标签: python sqlite


    【解决方案1】:

    相关问题,我将从中窃取 Alex Martelli 的答案:

    Parameter substitution for a SQLite "IN" clause

    这是我创建的数据:

    sqlite> create table x(a,b,c,d);
    sqlite> insert into x values(1, 10, 2, null);
    sqlite> insert into x values(2, 10, 3, null); 
    sqlite> insert into x values(3, 10, 4, null);
    

    以及获取它的 Python:

    >>> ids = [2, 3]
    >>> query = "SELECT b, c, d FROM x WHERE a IN ({0}) AND b > 5 ORDER BY c".format(','.join('?' for i in ids))
    >>> query
    'SELECT b, c, d FROM x WHERE a IN (?,?) AND b > 5 ORDER BY c'
    >>> conn.execute(query, ids).fetchall()
    [(10, 3, None), (10, 4, None)] 
    

    【讨论】:

    • +1,虽然这个解决方案在超过SQLITE_MAX_VARIABLE_NUMBER时会失败,即语句中占位符的个数(默认为999)。
    【解决方案2】:

    假设 ids_list 是您的 id 列表,而 tablename 是您的表:

    c = sqlite3.connect('foo').cursor()
    c.execute("""
    select Id, B, C, D
    from tablename
    where 
        Id in (%s) and 
        B >= 5
    order by C
    """ % ",".join( str(int(id)) for id in ids_list ))
    

    %s 替换是不好的做法,因为会受到 SQL 注入的影响。应该改用?,但它似乎不适用于in 子句。因此 str(int(id)) 技巧,用于“清理”(或检查)id 值(如果不是有效值将失败)

    【讨论】:

    • 既然可以正确使用占位符,为什么还要使用技巧?
    • 是的,如果列表的长度足够小,那么像您建议的那样动态构建占位符实际上会更好。占位符的主要目的是防止 SQL 注入,如果 ids 列表不是来自用户而是来自其他查询,例如,如果应该没问题。请注意,在后一种情况下,连接会更好:)
    【解决方案3】:

    我会使用以下内容:

    ids = [1, 3, 45, 67]
    cnx = sqlite3.connect('my_database.db')
    cursor = cnx.cursor()
    cursor.execute("""
        SELECT Id, B, C, D FROM table
        WHERE Id IN (%s) AND B > 5 ORDER BY C
        """ % ','.join('?' * len(ids)), tuple(ids))
    results = cursor.fetchall()
    

    【讨论】:

      【解决方案4】:

      我不知道python和sqlite之间的API,但是这个伪代码应该会有所帮助:

      list_id = [1,3,45,67]
      ids = ",".join(["%s" % el for el in list_id])
      print 'SELECT * FROM table WHERE B>5 AND ID IN (%s) ORDER BY C DESC' % (ids)
      

      【讨论】:

      • 请记住,您既不应该使用SELECT *,也不应该使用字符串连接构建查询(在此处使用准备好的语句)。
      猜你喜欢
      • 2011-09-13
      • 2021-10-21
      • 1970-01-01
      • 1970-01-01
      • 2014-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多