Mogrify和返回Psycopg2

4

我正在尝试生成自动查询。 我想使用executemany,但我需要使用returning语句,所以我做了这个:

def format_bind(cols, rows):
    return '(' + '), ('.join([', '.join(['%s'] * cols)] * rows) + ')'        

def insert_many(table, values, id_column):
                if not values:
                    return []

                keys = values[0].keys()
                conn = psycopg2.connect("dbname='db' user='postgres' host='localhost' password='postgres'")
            cursor = conn.cursor()
            query = cursor.mogrify("INSERT INTO {} ({}) VALUES {} RETURNING {}".format(table,
                                                                                         ', '.join(keys),
                                                                                         format_bind(len(keys), len(values)),
                                                                                         id_column),
                                   [tuple(v.values()) for v in values])
            cursor.execute(query)
            return [t[0] for t in (cursor.fetchall())]

问题是当我执行它时,会收到:error list index out of range。有人能帮我解决吗?

你为什么要同时使用Python字符串格式化和mogrify?http://initd.org/psycopg/docs/usage.html#the-problem-with-the-query-parameters - raphael
只是传递列名等内容,而不是变量。尽管如此,我还是在遵循一个帖子(请参见下面的其他评论)。 - Sam
1个回答

9
问题在于,我以为每个要插入的值都必须进行字符串参数内插。我来解释一下:
假设我有一个包含两个长度为三的字典的列表,里面存储了要插入的数据:
lst = [{'a': 21, 'b': 9, 'c': 33}, {'a': 76, 'b': 84, 'c': 46}]

为了插入这些值,我做了类似以下的操作:
query = curs.mogrify("INSERT INTO {} ({}) VALUES {} RETURNING {}".format(
                        table,
                        ', '.join(lst[0].keys()),
                        ', '.join(['%s'] * len(lst[0].values())),
                        'id'
                    ), [tuple(v.values()) for v in lst])

追加了三个'%s'(每个字典中的一个),总共有lst个字典。结果是异常信息error list index out of range,这是因为curs.mogrify()只期望每个字典中有一个'%s',所以在这种情况下只需要两个'%s'而不是三个。

因此,正确的插入lst数据的方式如下:

query = curs.mogrify("INSERT INTO {} ({}) VALUES {} RETURNING {}".format(
                            table,
                            ', '.join(lst[0].keys()),
                            ', '.join(['%s'] * len(lst)),
                            'id'
                        ), [tuple(v.values()) for v in lst])

len(lst[0].values()) 替换为 len(lst)

这是我解决问题的方法(因为我没有正确阅读示例代码而导致理解困难)。希望这可以帮到你。

Sam


额外补充一下,我也忽略了一个问题 - 在使用mogrify时,VALUES后面的%s没有括号包围。 - AiRiFiEd

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