在psycopg中,有没有合适的方法来处理postgresql函数返回的游标?

d6kp6zgx  于 2023-03-12  发布在  PostgreSQL
关注(0)|答案(2)|浏览(155)

我正试着和postgresql(14.0 build 1914,64位,windows平台),psycopg2(2.9.1,pip安装)和python 3.8.10交朋友。
我在数据库中创建了一个postgresql函数,它返回一个游标,如下所示

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();运行,然后将返回类似于“〈未命名门户1〉”的光标
仍然在pgAdmin4的查询工具中,我可以发出:

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

这将获得游标返回的行。
现在,我想使用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函数'get_rows'返回)。
如何从psycopg获取一个指针类对象,该对象提供对'get_rows'返回的游标的访问?
https://www.psycopg.org/docs/cursor.html说cursor.name是只读的,我看不出有什么明显的方法可以将'get_rows'中的游标与psycopg游标示例连接起来

sqxo8psd

sqxo8psd1#

您显示的游标链接指的是Python DB API游标,而不是Postgres游标。在第节中有一个示例说明如何在服务器端游标执行以下操作:
注意除了使用execute()执行的DECLARE之外,还可以使用命名游标来使用以其他方式创建的游标。例如,您可能有一个返回游标的PL/pgSQL函数:

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

可以通过使用常规的、未命名的Psycopg游标调用函数来读取游标内容:

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(cur 2)以释放服务器端游标。

cur2.close()
vatpfxk5

vatpfxk52#

前面的答案在我的例子中不起作用。下面是起作用的答案。第一个存储的函数(注意,没有refcursor参数):

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

然后按如下所示调用它(cursor返回一个名为refcursor的行):

cur = conn.cursor()
cur.callproc("func", [])
ref_cursor_name = cur.fetchone()[0]
ref_cursor = conn.cursor(ref_cursor_name)
data = ref_cursor.fetchall()

相关问题