使用psycopg2和POSTGRESQL在Python中更正SELECT查询的可选参数的函数定义
我想在函数中使用可选的过滤器参数从PostgreSQL数据库中进行选择,但我很难获得正确的语法使用psycopg2和POSTGRESQL在Python中更正SELECT查询的可选参数的函数定义,python,sql,python-3.x,postgresql,psycopg2,Python,Sql,Python 3.x,Postgresql,Psycopg2,我想在函数中使用可选的过滤器参数从PostgreSQL数据库中进行选择,但我很难获得正确的语法 def search(title: str = '', author: str = "", year: int, isbn: int): conn = psycopg2.connect( " dbname='mydb' user='postgres' password='pwd' host='localhost' port='5432' ") curs = conn.c
def search(title: str = '', author: str = "", year: int, isbn: int):
conn = psycopg2.connect(
" dbname='mydb' user='postgres' password='pwd' host='localhost' port='5432' ")
curs = conn.cursor()
curs.execute("SELECT * FROM book WHERE title=? OR author=? OR year=? OR isbn=?",
(title, author, year, isbn))
rows = curs.fetchall()
conn.close()
return rows
然后,我只想通过向函数传递一个参数(作者姓名)进行搜索,并使SELECT语句能够忽略/跳过尚未传递的字段。当我执行
print(search(author="John"))
输出是
Traceback (most recent call last):
File "backend.py", line 48, in <module>
print(search(author="John"))
File "backend.py", line 39, in search
(title, author, year, isbn))
psycopg2.errors.UndefinedFunction: operator does not exist: text =?
LINE 1: SELECT * FROM book WHERE title=? OR author=? OR year=? OR is...
^
HINT: No operator matches the given name and argument type. You might need to add an explicit type cast.
回溯(最近一次呼叫最后一次):
文件“backend.py”,第48行,在
打印(搜索(author=“John”))
搜索中第39行的文件“backend.py”
(标题、作者、年份、isbn))
psycopg2.errors.UndefinedFunction:运算符不存在:text=?
第1行:从书名=?或作者=?或年份=?还是。。。
^
提示:没有与给定名称和参数类型匹配的运算符。您可能需要添加显式类型转换。
我理解这与SELECT语句的数据类型和数据库列类型之间的不匹配有关,并且该错误反映了没有用于比较这两种数据类型的=运算符。但是如何定义函数参数和SELECT语句以使查询工作?psycopg2使用
%s
作为字符串替换的占位符,而不是?
。试着换一下衣服?到%s,它应该可以工作
编辑:
@关于你的where逻辑,冻糕提出了一个很好的观点。改变?到%s将修复语法错误,但仍无法修复逻辑。一种常见的处理方法是将所有参数默认为None
,并将查询更改为如下内容:
curs.execute("""
SELECT * FROM BOOK
WHERE (title = %(title)s OR %(title)s IS NULL)
AND (author = %(author)s OR %(author)s IS NULL)
AND (year = %(year)s OR %(year)s IS NULL)
AND (isbn = %(isbn)s OR %(isbn)s IS NULL)""",
{"title": title, "author": author, "year": year, "isbn": isbn})
这不是最有效的方法,但它可能是最简单的。
< P>可选地,考虑传递<代码> No.<代码>作为默认值,将其转换为<代码> NUL>代码>,并使用SQL的<代码> CueSeCs<代码>来选择第一个非空值。如果参数为None
,则查询中的列将彼此相等,实际上不应用任何筛选器
def search(title = None, author = None, year = None, isbn = None):
conn = psycopg2.connect(
" dbname='mydb' user='postgres' password='pwd' host='localhost' port='5432' ")
sql = """SELECT * FROM book
WHERE COALESCE(title, 'N/A') = COALESCE(%s, title, 'N/A')
AND COALESCE(author, 'N/A') = COALESCE(%s, author, 'N/A')
AND COALESCE(year, -1) = COALESCE(%s, year, -1)
AND COALESCE(isbn, -1) = COALESCE(%s, isbn, -1)
"""
curs = conn.cursor()
curs.execute(sql, (title, author, year, isbn))
rows = curs.fetchall()
conn.close()
return rows
谢谢现在感觉有点傻-我以前有一个sqlite数据库。我的逻辑对我来说似乎很好,至少它返回了正确的结果。避免在此处发布代码和结果,因为它不打算放在注释中。@oldnoob。。。如果您的所有字符串列都不维护空值,则会出现这种情况。调用零长度字符串,
'
,与NULL
不同。将行的作者
字段设置为NULL
后,我的查询仍然能够包括和排除使用各种参数组合的行搜索,为该特定字段返回None
。这不需要对每个列进行NOTNULL约束吗?或者使用与不同,而不是=
?@Jeremy,说得好<代码>合并
应位于等式的两侧。