Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python psycopg2游标_Python_Python 2.7_Cursor_Psycopg2 - Fatal编程技术网

Python psycopg2游标

Python psycopg2游标,python,python-2.7,cursor,psycopg2,Python,Python 2.7,Cursor,Psycopg2,从psycopg2文档: 执行数据库查询时,Psycopg游标通常会获取后端返回的所有记录,并将它们传输到客户端进程。如果查询返回大量数据,客户端将按比例分配大量内存。如果数据集太大,无法在客户端实际处理,则可以创建服务器端游标 我想查询一个可能有数千行的表,并对每一行执行一些操作。普通游标是否会将整个数据集带到客户机上?这听起来不太合理。代码大致如下: conn = psycopg2.connect(url) cursor = conn.cursor() cursor.execute(sql)

从psycopg2文档:

执行数据库查询时,Psycopg游标通常会获取后端返回的所有记录,并将它们传输到客户端进程。如果查询返回大量数据,客户端将按比例分配大量内存。如果数据集太大,无法在客户端实际处理,则可以创建服务器端游标

我想查询一个可能有数千行的表,并对每一行执行一些操作。普通游标是否会将整个数据集带到客户机上?这听起来不太合理。代码大致如下:

conn = psycopg2.connect(url)
cursor = conn.cursor()
cursor.execute(sql)
for row in cursor:
    do some stuff
cursor.close()
我希望这是一个流操作。第二个问题是关于游标的范围。在我的循环中,我想更新另一个表。我是否需要每次打开并关闭一个新光标?每个项目更新都应该在自己的事务中,因为我可能需要执行回滚

for row in cursor:
    anotherCursor = anotherConn.cursor()
    anotherCursor.execute(update)
    if somecondition:
        anotherConn.commit()
    else:
        anotherConn.rollback
cursor.close()
==========编辑:我对第一部分的回答========

好的,我将试着回答我问题的第一部分。通常的游标实际上会在调用execute时立即带来整个数据集,甚至在开始迭代结果集之前。您可以通过在每个步骤检查进程的内存占用来验证这一点。但对服务器端游标的需要实际上是由于postgres服务器而不是客户端的原因,本文对此进行了说明:

现在,这在文档中并不明显,但实际上可以在事务期间临时创建这样的游标。无需显式创建在数据库中返回refcursor的函数,以及特定的SLQ语句等。对于psycopg2,您只需在获取游标时给出名称,即可为该事务创建临时游标。因此,不是:

 cursor = conn.cursor()
你只需要:

 cursor = conn.cursor('mycursor')
就是这样,而且很有效。我假设在使用JDBC时,在设置fetchSize时,在幕后也会做同样的事情。它只是更透明一点。请参见此处的文档:


您可以通过查询同一事务中的pg_游标视图来测试这是否有效。服务器端光标在获取客户端光标后出现,在关闭客户端光标后消失。所以,底线是:我很高兴对我的代码做这样的更改,但我必须说,对于一个没有博士后经验的人来说,这是一个大难题。

事实上,你已经回答了这个问题;)

  • 是的,您应该使用服务器端游标以流式传输记录
  • 从文档:

    CREATE FUNCTION reffunc(refcursor) RETURNS refcursor AS $$
    BEGIN
        OPEN $1 FOR SELECT col FROM test;
        RETURN $1;
    END;
    $$ LANGUAGE plpgsql;
    
    在代码中:

    cur1 = conn.cursor()
    cur1.callproc('reffunc', ['curname'])
    
    cur2 = conn.cursor('curname')
    for record in cur2:     # or cur2.fetchone, fetchmany...
        # do something with record
        pass
    
  • 是的,如果您想使用服务器端游标获取行,您应该打开新游标

  • 那么,对于普通游标,只要我执行sql,整个结果集就会加载到内存中?如果我无法访问数据库来创建服务器端对象,该怎么办?难道没有类似JDBC结果集的东西吗?感谢JDBC驱动程序中不需要创建显式服务器端游标的示例:docs:执行数据库查询时,Psycopg游标通常会获取后端返回的所有记录,并将它们传输到客户端进程。如果查询返回大量数据,客户端将按比例分配大量内存。好的,谢谢您的回复。我想我已经明白了。实际上,不需要创建永久数据库对象,请参见我的答案。关于我问题的第二部分,它与服务器端游标无关。只有普通的游标和事务。通过在同一个查询中进行选择和更新,您可以避免所有的流量和游标杂务。发布真实的查询,很可能你会得到更好的答案。我猜你的意思是用“updatewhere”语句,对吗?在我的用例中,处理要比这复杂得多。我指的是CTE查询。不管多么复杂,哇。实际上,只需给光标一个名称即可启用流式处理。谢谢