从ARRAY加入数据或嵌套值

时间:2015-04-09 17:36:23

标签: postgresql postgresql-9.1 psycopg2

我使用psycopg2向postgresql查询提供一些枚举数据。这些数据需要连接到我用来返回我想要的数据的表,这样我就可以按正确的顺序获取它们。似乎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

正如您所看到的,我使用数组来选择我想要的ID,但也提供另一列来排序行,但我无法使数据表现为连接表。在此示例中,我收到以下错误:返回函数需要列定义列表"记录"

而不是ARRAY,数据可以提供为:((0,34523), (1, 3453))

除非psycopg2允许VALUES列表,例如:VALUES (0,34523), (1, 3453)

我正在使用postgresql 9.1.13

2 个答案:

答案 0 :(得分:0)

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

    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
    """, ())

答案 1 :(得分:0)

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

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

  

如果包含要发送到数据库的数据的变量来自不受信任的来源(例如网站上发布的表单),攻击者可能很容易制作出格式错误的字符串,要么获取对未经授权的数据的访问权限,要么执行破坏性操作数据库。这种形式的攻击称为SQL注入,并且已知是对数据库服务器的最广泛的攻击形式之一。在继续之前,请将此页面作为备忘录打印并挂在桌面上。

     

Psycopg可以自动将Python对象与SQL文字进行转换:使用此功能,您的代码将更加健壮和可靠。我们必须强调这一点:

     

警告永远不要,永远不要使用Python字符串连接(+)或字符串参数插值(%)将变量传递给SQL查询字符串。甚至在枪口下也没有。

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

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