使用Python和SQLite进行关键字搜索

0 投票
2 回答
1860 浏览
提问于 2025-04-16 06:43

我有一个游戏服务器的插件,用来记录地图上的变化。数据库里有一些条目,格式是这样的:id 是一个整数并且是主键,matbefore 是一个整数,matafter 也是一个整数,name 是一个最多50个字符的字符串,date 是一个日期。我正在尝试创建一个函数,这个函数可以接收一个列名、一个整数、一个字符串,或者一个整数或字符串的元组,还有一个关键词,然后找到符合条件的条目。目前我写的代码是这样的 -

def readdb(self,keyword,column,returncolumn = "*"):
    self.memwrite
    if isinstance(keyword, int) or isinstance(keyword,str):
        entry = [keyword]
    qmarks = ("? OR " * len(entry))[:-4]
    statement = 'SELECT all {0} FROM main WHERE {1} is {2}'.format(returncolumn,column,qmarks)
    print(qmarks)
    self.memcursor.execute(statement, entry)
    return(self.memcursor.fetchall())

这里的关键词是要搜索的关键词,column 是要搜索的列,returncolumn 是要返回的列。我想知道为什么这段代码总是找不到任何行,比如说 - 返回 None,无论我在函数里输入什么。看起来如果我在控制台里直接执行这些操作是没问题的,但如果把它们放在函数里就不行了。

2 个回答

0
  1. 不太明白这段代码想干嘛。你是想用 self.memwrite() 吗?
  2. def readdb(self,keyword,column,returncolumn = "*"):
        self.memwrite                                             # 1. 
        if isinstance(keyword, int) or isinstance(keyword,str):   # 2.
            entry = [keyword]                                     # 3.
        qmarks = ("? OR " * len(entry))[:-4]                      # 4.
        statement = 'SELECT all {0} FROM main WHERE {1} is {2}'.format(returncolumn,column,qmarks)
        print(qmarks)                                             # 5.
        self.memcursor.execute(statement, entry)
        return(self.memcursor.fetchall())
    

    可以改成 if isinstance(keyword, (int,str)) 这样。

    或者更好的是,不要去检查类型。因为你写的代码里,keyword 不能是 Unicode 字符串。为什么要这样限制呢?在这种情况下,我觉得用 try...except... 结构来捕捉后面的错误会更好,而不是限制类型。

  3. 所以最多 len(entry) = 1。注意,如果 keyword 不是 int 或 str 类型,可能根本到不了这一行。那样的话,第 (4) 行会出错,因为 entry 还没有定义。
  4. 这段代码也可以写成

    qmarks = ' OR '.join(['?']*len(entry))
    

    这样可以避免在 ("? OR " *1)[:-4] 中使用那个有点神秘的数字 4。

  5. 你在这里看到了什么?如果是空的,那应该是个线索。此外,运行 print(statement) 可以更全面地了解传给 .execute() 的内容。

  6. 也许可以试试

    statement = 'SELECT {0} FROM main WHERE {1} = ?'.format(
                 returncolumn,column)
    

    特别是,is 应该改成 =

1

如果 entry 是一个列表(就像昨天的问题那样),那么这个写法是行不通的。

>>> returncolumn = "*"
>>> column = "name"
>>> entry = ["Able", "Baker", "Charlie"]
>>> qmarks = ("? OR " * len(entry))[:-4]
>>> statement = 'SELECT all {0} FROM main WHERE {1} is {2}'.format(returncolumn,
column,qmarks)
>>> print statement
SELECT all * FROM main WHERE name is ? OR ? OR ?

SQLite 会看到的是:

SELECT all * FROM main WHERE name is 'Able' OR 'Baker' OR 'Charlie'

这不是正确的语法,因为你需要用 =,而不是 is

即使你把这个问题修正了,比如用整数查询:

SELECT all * FROM main WHERE id = 1 or 2 or 3

你也会得到一些奇怪的结果,因为这实际上意味着 WHERE ((id = 1) or 2) or 3),而不是你想的那样……你需要写成 WHERE id = 1 or id = 2 or id = 3,或者(回到昨天的问题) WHERE id IN (1,2,3)

撰写回答