如何将服务器端游标与 django 和 psycopg2 一起使用?
How can I use server-side cursors with django and psycopg2?
我正尝试在 psycop2 中使用服务器端光标,详见 this blog post。本质上,这是通过
实现的
from django.db import connection
if connection.connection is None:
cursor = connection.cursor()
# This is required to populate the connection object properly
cursor = connection.connection.cursor(name='gigantic_cursor')
当我执行查询时:
cursor.execute('SELECT * FROM %s WHERE foreign_id=%s' % (table_name, id))
我得到一个 ProgrammingError
:
psycopg2.ProgrammingError: can't use a named cursor outside of transactions
我曾天真地尝试使用
创建交易
cursor.execute('BEGIN')
在执行 SELECT
语句之前。但是,这会导致 cursor.execute('BEGIN')
行产生相同的错误。
我也试过使用
cursor.execute('OPEN gigantic_cursor FOR SELECT * FROM %s WHERE foreign_id=%s' % (table_name, id))
但我得到了相同的结果。
如何在 django 中进行交易?
应在事务内部使用游标。您需要定义一个事务并在其中使用游标。
-- need to be in a transaction to use cursors.
摘自 here.
正如你在问题中提到的,但我会在这里为未来的读者重申:也可以使用明确命名的游标而不绕过 Django 的 public API:
from django.db import connection, transaction
with transaction.atomic(), connection.cursor() as cur:
cur.execute("""
DECLARE mycursor CURSOR FOR
SELECT *
FROM giant_table
""")
while True:
cur.execute("FETCH 1000 FROM mycursor")
chunk = cur.fetchall()
if not chunk:
break
for row in chunk:
process_row(row)
由于 isolation_level='AUTOCOMMIT'
在我的 sqlalchemy.create_engine
中,我得到了这个。
我正尝试在 psycop2 中使用服务器端光标,详见 this blog post。本质上,这是通过
实现的from django.db import connection
if connection.connection is None:
cursor = connection.cursor()
# This is required to populate the connection object properly
cursor = connection.connection.cursor(name='gigantic_cursor')
当我执行查询时:
cursor.execute('SELECT * FROM %s WHERE foreign_id=%s' % (table_name, id))
我得到一个 ProgrammingError
:
psycopg2.ProgrammingError: can't use a named cursor outside of transactions
我曾天真地尝试使用
创建交易cursor.execute('BEGIN')
在执行 SELECT
语句之前。但是,这会导致 cursor.execute('BEGIN')
行产生相同的错误。
我也试过使用
cursor.execute('OPEN gigantic_cursor FOR SELECT * FROM %s WHERE foreign_id=%s' % (table_name, id))
但我得到了相同的结果。
如何在 django 中进行交易?
应在事务内部使用游标。您需要定义一个事务并在其中使用游标。
-- need to be in a transaction to use cursors.
摘自 here.
正如你在问题中提到的,但我会在这里为未来的读者重申:也可以使用明确命名的游标而不绕过 Django 的 public API:
from django.db import connection, transaction
with transaction.atomic(), connection.cursor() as cur:
cur.execute("""
DECLARE mycursor CURSOR FOR
SELECT *
FROM giant_table
""")
while True:
cur.execute("FETCH 1000 FROM mycursor")
chunk = cur.fetchall()
if not chunk:
break
for row in chunk:
process_row(row)
由于 isolation_level='AUTOCOMMIT'
在我的 sqlalchemy.create_engine
中,我得到了这个。