检查 psycopg2/postgresql 中是否存在 python 值列表

Checking existence of list of python values in psycopg2/postgresql

我有一个 python 值列表和一个包含特定列的 postgresql table。对于 python 列表中的每个元素,我想知道 table 中是否有具有该 ID 的任何行。

例如,假设我有这个 python 列表:

vals = [4, 8, 15, 16, 23, 42]

还有查询:

select my_col from my_table;

给出:

[4, 5, 6, 7, 8]

那么我想要一个返回的查询:

[True, True, False, False, False, False]

我可以遍历列表并为每个值执行一个新的 "select exists",但我想知道是否有一种方法可以在一次调用中完成?

我仅限于 postgresql 9.0

我认为这需要混合使用字符串格式和占位符(因为 vals 中的每个项目需要一个 %s):

vals = [4, 8, 15, 16, 23, 42]

query = 'select distinct(my_col) from my_table where my_col in ('
query += ', '.join(['%s'] * len(vals))
query += ')'

cursor.execute(query, vals)
theset = {t[0] for t in cursor.fetchall()}

theboollist = [v in theset for v in vals]

这种方法应该保证您发送到数据库的数据量(对于 where ... in 子句)和您从中返回的数据量都是 O(N) 其中 N等于len(vals);我认为从逻辑上讲不可能比 big-O 做得更好。

这个问题更多的是关于 SQL 而不是关于 Python 或 psycopg。我会使用这样的查询:

SELECT my_col = ANY(your_array_here) FROM my_table;

获得结果 "table order" 或:

SELECT A.x = ANY(SELECT my_col FROM my_table) 
  FROM (SELECT * FROM unnest(your_array_here) x) A;

得到 "vals order" 中的结果。

幸运的是,psycopg 提供了一个默认适配器,可以将 Python 列表转换为 PostgreSQL 数组,代码非常简单:

curs.execute("SELECT my_col = ANY(%s) from my_table", (vals,))

或:

curs.execute("""SELECT A.x = ANY(SELECT my_col FROM my_table) 
                  FROM (SELECT * FROM unnest(%s) x) A""", (vals,))

请注意,绑定变量参数应该是 dict 或元组,并且您想将完整列表绑定到查询中的单个变量,这意味着您应该使用 1 元素元组 ((vals,)) 而不是尝试直接传递 vals