有没有正确的方法来处理从 psycopg 中的 postgresql 函数返回的游标?

Is there a proper way to handle cursors returned from a postgresql function in psycopg?

我正在尝试与 postgresql(windows 上的 14.0 build 1914 64 位)、psycopg2(使用 pip 安装的 2.9.1)和 python 3.8.10 交朋友 windows.

我在数据库中创建了一个 postgresql 函数,return它是一个游标,如下所示

CREATE get_rows 
...
RETURNS refcursor
...
DECLARE
    res1 refcursor;
BEGIN   
    OPEN res1 FOR
        SELECT some_field, and_another_field FROM some_table;

    RETURN res1;
END

函数可以是 运行 来自 pgAdmin4 Quert 工具 SELECT get_rows(); 然后 return 一个像“

这样的光标

仍在 pgAdmin4 的查询工具中,我可以发出:

BEGIN;
SELECT get_rows();
FETCH ALL IN "<unnamed portal 2>"; -- Adjust counter number

这将使我得到游标 return 编辑的行。

现在我想使用 psycopg 而不是 pgAdmin4 来复制它

我有以下代码

conn = psycopg2.connect("dbname='" + db_name + "' "\
                                "user='" + db_user + "' " +\
                                "host='" + db_host + "' "+\
                                "password='" + db_passwd + "'")
cursor = conn.cursor()
cursor.callproc('get_rows')
print("cursor.description: ", end = '')
print(cursor.description)
for record in cursor:
    print("record: ", end = '')
    print (record)

以上代码仅在 psycopg 创建的游标的单个记录中给出了游标字符串名称(由 postgresql 函数return编辑'get_rows')。

我怎样才能从 psycopg 中获取游标-class 对象,该对象提供对 'get_rows' 编辑的游标 return 的访问?

https://www.psycopg.org/docs/cursor.html 说 cursor.name 是只读的,我没有看到将光标从 'get_rows' 连接到 psycopg 光标实例

的明显方法

您显示的游标 link 指的是 Python DB API 游标,而不是 Postgres 游标。 Server side cursor 部分有一个如何做你想做的事的例子:

Note It is also possible to use a named cursor to consume a cursor created in some other way than using the DECLARE executed by execute(). For example, you may have a PL/pgSQL function returning a cursor:

CREATE FUNCTION reffunc(refcursor) RETURNS refcursor AS $$
BEGIN
    OPEN  FOR SELECT col FROM test;
    RETURN ;
END;
$$ LANGUAGE plpgsql;

You can read the cursor content by calling the function with a regular, non-named, Psycopg cursor:

cur1 = conn.cursor()
cur1.callproc('reffunc', ['curname'])

and then use a named cursor in the same transaction to “steal the cursor”:

cur2 = conn.cursor('curname')
for record in cur2:     # or cur2.fetchone, fetchmany...
    # do something with record
    pass

更新

确保关闭 named cursor(cur2) 以释放服务器端游标。所以:

cur2.close()