Ich versuche, mich mit postgresql (14.0 Build 1914 64-Bit unter Windows), psycopg2 (2.9.1 installiert mit Pip) und Python 3.8.10 unter Windows anzufreunden.
Ich habe eine Postgresql-Funktion in einer Datenbank erstellt, die einen Cursor zurückgibt, so etwas wie unten
CREATE get_rows
...
RETURNS refcursor
...
DECLARE
res1 refcursor;
BEGIN
OPEN res1 FOR
SELECT some_field, and_another_field FROM some_table;
RETURN res1;
END
Die Funktion kann vom pgAdmin4 Quert-Tool ausgeführt
SELECT get_rows();
werden und gibt dann einen Cursor wie „<unbenanntes Portal 1>" zurück.
Noch im Abfragetool in pgAdmin4 kann ich Folgendes ausgeben:
BEGIN;
SELECT get_rows();
FETCH ALL IN "<unnamed portal 2>"; -- Adjust counter number
Und das bringt mir die Zeilen, die vom Cursor zurückgegeben werden.
Jetzt möchte ich dies mit psycopg anstelle von pgAdmin4 replizieren
Ich habe den folgenden Code
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)
Der obige Code gibt nur den Namen der Cursorzeichenfolge (wie von der Postgresql-Funktion „get_rows" zurückgegeben) in dem einzelnen Datensatz des Cursors an, der von psycopg erstellt wurde.
Wie kann ich ein Objekt der Cursorklasse von psycopg erhalten, das Zugriff auf den von 'get_rows' zurückgegebenen Cursor bietet?
https://www.psycopg.org/docs/cursor.html sagt, dass cursor.name schreibgeschützt ist und ich sehe keinen offensichtlichen Weg, den Cursor von ‚get_rows' mit einer psycopg-Cursor-Instanz zu verbinden
Lösung des Problems
Der von Ihnen angezeigte Cursor-Link bezieht sich auf den Python-DB-API-Cursor, nicht auf den Postgres-Cursor. Hier finden Sie ein Beispiel dafür, wie Sie das tun können, was Sie möchten Serverseitiger Cursor im Abschnitt:
Hinweis Es ist auch möglich, einen benannten Cursor zu verwenden, um einen Cursor zu verbrauchen, der auf andere Weise als mit dem von execute() ausgeführten DECLARE erstellt wurde. Beispielsweise können Sie eine PL/pgSQL-Funktion haben, die einen Cursor zurückgibt:
CREATE FUNCTION reffunc(refcursor) RETURNS refcursor AS $$
BEGIN
OPEN $1 FOR SELECT col FROM test;
RETURN $1;
END;
$$ LANGUAGE plpgsql;
Sie können den Cursorinhalt lesen, indem Sie die Funktion mit einem normalen, unbenannten Psycopg-Cursor aufrufen:
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
AKTUALISIEREN
Stellen Sie sicher, dass named cursor
(cur2) geschlossen wird, um den serverseitigen Cursor freizugeben. So:
cur2.close()
Keine Kommentare:
Kommentar veröffentlichen