在Python程序中查询SQLite数据库中的多个任意标签
我正在尝试用Python创建一个标签应用,功能类似于流行的*booru网站。不过,我在设置搜索功能时遇到了麻烦,无法有效地查询我的数据库并返回正确的数据。
我希望的效果是,我可以在搜索框中输入任意数量的标签,然后返回与这些标签相关的帖子。此外,我还想在搜索查询中添加类似“!tag”的内容,以排除某个特定标签的帖子。目前的情况是,我只能同时查询两个标签,而且这些标签是固定在查询中的,我不知道怎么更改它们。
我使用了这里的一个答案作为模板: https://stackoverflow.com/a/62731660
我有三个表:
posts posttags tags
---- ---- ----
id postid | tagid id | tagname
这是我目前的代码:
res = dbCursor.execute("SELECT postid FROM posttags JOIN tags on tagid=id WHERE tags.tagname in (?) GROUP BY postid HAVING count(DISTINCT tagname) = ?", (query, len(query)))
print(res.fetchall())
其中 query
是搜索的关键词,len(query)
是查询中关键词的数量。
现在的情况是,标签会被传递给 execute
函数,但 print(res.fetchall())
只返回一个空列表。如果我把查询中的 "(?)" 替换成 ('tag1','tag2'),那就能正常工作,返回相应的帖子ID。把 query
格式化成带括号的形式,要么会出现语法错误,要么像之前一样什么都不返回。
现在我只能查询我在SQL查询中硬编码的特定数量的标签,但我希望能够查询用户提交的任意数量的标签。有没有办法用SQL查询任意数量的标签?
我在Stack Overflow上查了多个答案,但似乎所有的答案都需要把搜索参数固定在查询中。我可以手动拆分查询并插入这些关键词吗?还是有更好的方法?任何信息都很感谢!
1 个回答
0
我最后直接操作了查询字符串。我知道这样做不好,但这是我唯一知道的办法。搜索的关键词没有经过处理,这样就容易受到SQL注入攻击。
下面是我怎么做的。代码中的注释应该能帮助你理解发生了什么:
import sqlite3 as sql
def find():
# Get the value of a tkinter search bar with some formatting
# Converting it to a set and then a list removes duplicates
query = list(set(str(modify.get()).lower().split()))
# Create an empty list to store our found posts in
postsbytag = []
# Connect to our sqlite database
dbConnection = sql.connect('database.db')
dbCursor = dbConnection.cursor()
# Further format the results of our search bar
mystring = str(tuple(query))
# Get the number of tags searched
querylength = len(tuple(query))
# Some extra formatting to get the query to work if we only stitch in one tag
if querylength == 1:
mystring = mystring.replace(',','')
# Generate our sql query based on our search
myquery = "SELECT postid FROM posttags JOIN tags on tagid=id WHERE tags.tagname in " + mystring + " GROUP BY postid HAVING count(DISTINCT tagname) = " + str(querylength)
# Execute the query against the database
res = dbCursor.execute(myquery)
# Set the result of our query to variable
tagiddata = res.fetchall()
# From here we can process the information in tagiddata and do what we want with it.
# Close the database connection and exit the function
dbConnection.close()