如何检查一个值是否在列表中或者列表是否为空?

7
我正在使用 psycopg2 以Python 3访问PostgreSQL数据库,我试图进行查询,其中我想选择名字在列表中的所有用户,如果列表不为空。 如果提供的列表为空,则希望忽略该条件,即选择所有用户而不考虑其名称。

我已经尝试了以下三种方法:

# Using list
cursor.execute(
    "SELECT age FROM user WHERE %(names) = '{}' OR user.name IN %(names)s",
    {'names': []},
)

# Using tuple
cursor.execute(
    "SELECT age FROM user WHERE %(names) = () OR user.name IN %(names)s",
    {'names': ()},
)

# Using both list and tuple
cursor.execute(
    "SELECT age FROM user WHERE %(names_l) = '{}' OR user.name IN %(names_t)s",
    {'names_l': [], 'names_t': ()},
)

但是它们都会在某个地方引发无效语法错误:

# Using list
psycopg2.ProgrammingError: syntax error at or near "'{}'"
LINE 17:         user.name IN '{}'

# Using tuple
psycopg2.ProgrammingError: syntax error at or near ")"
LINE 16:         () == ()

# Using both list and tuple
psycopg2.ProgrammingError: syntax error at or near ")"
LINE 17:         user.name IN ()
1个回答

4

对于可选参数,您需要一个SQL where子句,例如:

where column = :parameter or :parameter is null

如果参数为null,则将返回所有行,否则将只返回满足条件的行。

Psycopg将Python的list适配到Postgresql的array。要检查任何一个Postgresql的array值是否等于某个值:

where column = any (array[value1, value2])

为了从一个空的Python列表中获取适用于Postgresql null的Python None,请使用以下代码:
parameter = [] or None

将一个字典传递给 cursor.execute 方法可以避免参数在 parameters 参数中的重复:
names = ['John','Mary']

query = """
    select age
    from user
    where user.name = any (%(names)s) or %(names)s is null
"""
print (cursor.mogrify(query, {'names': names or None}).decode('utf8'))
#cursor.execute(query, {'names': names or None})

输出:

select age
from user
where user.name = any (ARRAY['John', 'Mary']) or ARRAY['John', 'Mary'] is null

当列表为空时:
select age
from user
where user.name = any (NULL) or NULL is null

http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries


我现在感觉真的很傻,之前竟然没意识到可以使用SQL的“NULL”,尽管我知道它的存在和作用...不过这个方法很不错,谢谢你的帮助! :) - Markus Meskanen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接