在SQLite中使用预处理语句进行SELECT查询

5 投票
3 回答
17717 浏览
提问于 2025-04-16 23:12

我正在做一个小项目,目的是整理人们的漫画书,并把相关信息存储在一个SQL数据库里。为了确保正确性,我使用了预处理语句,而不是Python自带的字符串操作符,但我总是搞不定。下面是我写的一个简短代码片段,用来说明我遇到的问题:

#!/usr/bin/env python

import sqlite3

connection = sqlite3.connect("MyComicBox.db")

curs = connection.cursor()

curs.execute("CREATE TABLE IF NOT EXISTS comic_collection (id INTEGER PRIMARY KEY, series TEXT, publisher TEXT, issue TEXT, tags TEXT)")

connection.commit()

def addComic(series = "", publisher = "", issue = "", tags = ""):
    curs.execute("INSERT INTO comic_collection (series, publisher, issue, tags) VALUES(?, ?, ?, ?)", (series, publisher, issue, tags))
    connection.commit()

def search(attribute, val):
    """
    Do an SQL query for all comics where attribute LIKE val and return a list of them.
    """

#   cmd = "SELECT * from comic_collection WHERE %s LIKE '%s'" % (attribute, val)
#   curs.execute(cmd)

    cmd = "SELECT * from comic_collection WHERE ? LIKE ?"
    curs.execute(cmd, (attribute, val))

    results = []

    for comic in curs:
        results.append(comic)

    return results

addComic(series = "Invincible Iron Man", issue = "500", publisher = "Marvel Comics", tags = "Iron Man; Spider-Man; Mandarin")


searchResults = search("issue", "500")

for item in searchResults:
    print item

我的问题出在搜索功能上。查询没有返回任何结果,除非我把用?操作符执行cmd的那两行代码替换成用Python自带字符串操作符执行cmd的那两行(被注释掉的)。有没有人能帮我找出我哪里做错了?

3 个回答

-3

根据我对sqlite C API中预处理语句的记忆,你可能需要这样写:

cmd = "SELECT * from comic_collection WHERE ?1 LIKE ?2"
7

你不能用占位符来表示列名——占位符只能用来表示值。所以这样做是可以的:

cmd = "SELECT * from comic_collection WHERE %s LIKE ?" % attribute
curs.execute(cmd, (val,))
5

你使用的 attribute 是不对的。想象一下,? 已经包含了它周围的 '' 符号。

一种做法是这样:

cmd = "SELECT * from comic_collection WHERE %s LIKE ?" % attribute
curs.execute(cmd, val)

但是你一定要确保这个 attribute 不是来自不可信的来源,或者它只包含有效的值,可能需要通过

assert attribute in ('series', 'publisher', 'issue', 'tags')

撰写回答