为什么psycopg2不允许我们在同一个连接中打开多个服务器端游标?

时间:2015-08-04 11:31:35

标签: psycopg2 amazon-redshift

我很好奇为什么psycopg2不允许在同一个连接中打开多个服务器端游标(http://initd.org/psycopg/docs/usage.html#server-side-cursors)。我最近遇到了这个问题,我必须通过客户端游标替换第二个游标来解决它。但我还是想知道是否有办法做到这一点
例如,我在Amazon Redshift上有这两个表:

CREATE TABLE tbl_account (
acctid varchar(100),
regist_day date
);

CREATE TABLE tbl_my_artist (
user_id varchar(100),
artist_id bigint
);

INSERT INTO tbl_account
(acctid, regist_day)
VALUES
('TEST0000000001', DATE '2014-11-23'),
('TEST0000000002', DATE '2014-11-23'),
('TEST0000000003', DATE '2014-11-23'),
('TEST0000000004', DATE '2014-11-23'),
('TEST0000000005', DATE '2014-11-25'),
('TEST0000000006', DATE '2014-11-25'),
('TEST0000000007', DATE '2014-11-25'),
('TEST0000000008', DATE '2014-11-25'),
('TEST0000000009', DATE '2014-11-26'),
('TEST0000000010', DATE '2014-11-26'),
('TEST0000000011', DATE '2014-11-24'),
('TEST0000000012', DATE '2014-11-24')
;

INSERT INTO tbl_my_artist
(user_id, artist_id)
VALUES
('TEST0000000001', 2000011247),
('TEST0000000001', 2000157208),
('TEST0000000001', 2000002648),
('TEST0000000002', 2000383724),
('TEST0000000003', 2000002546),
('TEST0000000003', 2000417262),
('TEST0000000004', 2000076873),
('TEST0000000004', 2000417266),
('TEST0000000005', 2000077991),
('TEST0000000005', 2000424268),
('TEST0000000005', 2000168784),
('TEST0000000006', 2000284581),
('TEST0000000007', 2000284581),
('TEST0000000007', 2000000642),
('TEST0000000008', 2000268783),
('TEST0000000008', 2000284581),
('TEST0000000009', 2000088635),
('TEST0000000009', 2000427808),
('TEST0000000010', 2000374095),
('TEST0000000010', 2000081797),
('TEST0000000011', 2000420006),
('TEST0000000012', 2000115887)
;

我想从这两个表中选择,然后用查询结果做一些事情 我使用2个服务器端游标,因为我的查询中需要2个嵌套循环。我想使用服务器端游标,因为结果可能非常大 我使用fetchmany()而不是fetchall(),因为我在单节点集群上运行。

这是我的代码:

import psycopg2
from psycopg2.extras import DictCursor

conn = psycopg2.connect('connection parameters')

cur1 = conn.cursor(name='cursor1', cursor_factory=DictCursor)
cur2 = conn.cursor(name='cursor2', cursor_factory=DictCursor)

cur1.execute("""SELECT acctid, regist_day FROM tbl_account
                WHERE regist_day <= '2014-11-25'
                ORDER BY 1""")
for record1 in cur1.fetchmany(50):
    cur2.execute("""SELECT user_id, artist_id FROM tbl_my_artist
                    WHERE user_id = '%s'
                    ORDER BY 1""" % (record1["acctid"]))
    for record2 in cur2.fetchmany(50):
        print '(acctid, artist_id, regist_day): (%s, %s, %s)' % (
            record1["acctid"], record2["artist_id"], record1["regist_day"])
        # do something with these values

conn.close()

运行时出现错误:

Traceback (most recent call last):
  File "C:\Users\MLD1\Desktop\demo_cursor.py", line 20, in <module>
    for record2 in cur2.fetchmany(50):
  File "C:\Python27\lib\site-packages\psycopg2\extras.py", line 72, in fetchmany
    res = super(DictCursorBase, self).fetchmany(size)
InternalError: opening multiple cursors from within the same client connection is not allowed.

当我尝试从第二个光标获取结果时,在第20行发生了该错误。

1 个答案:

答案 0 :(得分:0)

四年后的答案,但是有可能在同一连接中打开多个游标。 (可能是库已更新,可以解决上述问题。)

注意事项是,只允许使用命名游标调用execute()一次,因此,如果在fetchmany循环中重用其中一个游标,则需要删除该名称或创建另一个“匿名”游标。