JOIN 来自 ARRAY 或嵌套值的数据

JOIN data from ARRAY or nested values

我正在使用 psycopg2 将一些枚举数据呈现给 postgresql 查询。此数据需要连接到我正在使用的 table 到 return 我想要的数据,以便我可以按正确的顺序获取它们。看来 psycopg2 只允许将数据作为数组或单个括号值提供。这是一次查询尝试的示例:

 SELECT table_a.foo, table_b.bar
 FROM table_a
 JOIN table_b USING(id)
 JOIN unnest(ARRAY[(0,34523), (1, 3453)]) AS baz (index, id) USING (id)
 ORDER BY baz.index ASC

如您所见,我正在使用数组 select 我想要的 ID,但还提供了另一列来对行进行排序,但我无法让数据表现得像一个连接的 table。在此示例中,我收到以下错误:函数 returning "record"

需要列定义列表

数据可以提供为:((0,34523), (1, 3453))

,而不是数组

除非 psycopg2 允许像这样的 VALUES 列表:VALUES (0,34523), (1, 3453)?

我正在使用 postgresql 9.1.13

我确实找到了解决方案,其中涉及分部分构建查询字符串:

    enumerated_ids = ','.join(self.cur.mogrify("(%s, %s)", x) for x in enumerate(ids))

    self.execute("""
        SELECT table_a.foo, table_b.bar
        FROM table_a
        JOIN table_b USING(id)
        JOIN (VALUES """+ enumerated_ids +""") AS baz (index, id) USING (id)
        ORDER BY baz.index ASC
    """, ())

重要提示:接受的答案非常危险,不应使用。

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

If the variables containing the data to send to the database come from an untrusted source (such as a form published on a web site) an attacker could easily craft a malformed string, either gaining access to unauthorized data or performing destructive operations on the database. This form of attack is called SQL injection and is known to be one of the most widespread forms of attack to database servers. Before continuing, please print this page as a memo and hang it onto your desk.

Psycopg can automatically convert Python objects to and from SQL literals: using this feature your code will be more robust and reliable. We must stress this point:

Warning Never, never, NEVER use Python string concatenation (+) or string parameters interpolation (%) to pass variables to a SQL query string. Not even at gunpoint.

但是,您可以定义自己的采用者:

class Values(object):
    def __init__(self, value):
        self.storage = value

def adapt_values(value):
    return AsIs("(VALUES(" + ", ".join(map(lambda x: str(x), value.storage)) + ")")

register_adapter(Values, adapt_values)

cur.execute("SELECT X, Y FROM Table JOIN %s V(A, B) ON A = X AND Y = B", [Values(my_values)])

文档:http://initd.org/psycopg/docs/advanced.html#adapting-new-python-types-to-sql-syntax