我正在尝试使用 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') 替换查询中的“(?)”,它可以正常工作并返回适当的 postid。将 query
格式化为具有 backets 等,要么抛出语法错误,要么像以前一样不返回任何内容。
现在我只能查询硬编码到sql查询中的特定数量的标签,但我想查询用户提交的任意数量的标签。有没有办法可以使用 sql 查询任意数量的标签?
我已经在堆栈溢出上检查了多个答案,但所有这些答案似乎都需要将搜索参数烘焙到查询中。我可以手动切碎查询并插入术语,还是有更好的方法来解决这个问题?任何信息表示赞赏!
我最终直接操作查询字符串。我知道这是不好的做法,但这是我知道如何做到这一点的唯一方法。搜索词也未转义,这使得这很容易发生 sql 注入。
我就是这样做的。代码注释应该有助于解释发生了什么:
import sqlite3 as sql
def find():
# Get the value of a tkinter search bar with some formatting
query = str(searchbar.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()