2009-11-14 7 views
16

ich als Beispiel die einfachste der SQL-Funktionen übernehmen werden:Warum führt psycopg2 keine meiner SQL-Funktionen aus? (Indexerror: Tupelindex außerhalb des Bereichs)

CREATE OR REPLACE FUNCTION skater_name_match(INTEGER,VARCHAR) 
RETURNS BOOL AS 
$$ 
    SELECT $1 IN (SELECT skaters_skater.competitor_ptr_id FROM skaters_skater 
    WHERE name||' '||surname ILIKE '%'||$2||'%' 
    OR surname||' '||name ILIKE '%'||$2||'%'); 
$$ LANGUAGE SQL; 

Wenn ich kopieren und diese in psql (PostgreSQL Shell), dann führt es ohne Probleme .

Wenn ich ein Stück Python-Code wie folgt schreiben (mit einem echten Datenbanknamen und Benutzer natürlich):

import psycopg2 

sql_function_above = '''CREATE OR REPLACE FUNCTION skater_name_match(INTEGER,VARCHAR) 
RETURNS BOOL AS 
$$ 
    SELECT $1 IN (SELECT skaters_skater.competitor_ptr_id FROM skaters_skater 
    WHERE name||' '||surname ILIKE '%'||$2||'%' 
    OR surname||' '||name ILIKE '%'||$2||'%'); 
$$ LANGUAGE SQL;''' 

try: 
    connection = psycopg2.connect("dbname='x' user='x' host='localhost' password='x'"); 
except: 
    print "I am unable to connect to the database" 

cursor = connection.cursor() 
cursor.execute(sql_function_above) 

Es scheint auszuführen (es gibt mir keinen Fehler), aber wenn ich in die Datenbank schaue, ist die Funktion nicht da.

Wenn ich versuche, den Code in Django auszuführen, indem es in eine app/SQL/model.sql Datei setzt ich folgende Fehlermeldung während syncdb erhalten:

IndexError: tuple index out of range 

Wenn ich versuche, meine eigene Verwaltung zu schreiben. Py-Befehl, der die SQL ausführen würde, bekomme ich den gleichen Fehler.

Was geht hier vor? Wäre sehr dankbar für jeden, der etwas Licht in diese Sache bringen könnte :) Ich bin immer noch ein Neuling, wenn es um Python und Django geht, also habe ich vielleicht etwas Offensichtliches übersehen.

+1

Wären Sie in der Lage, die tatsächliche Anweisung hinzuzufügen, die Sie in "Cursor ausführen".execute (sql_function_above) "(oder zeigen Sie an, wo Sie 'sql_function_above' definieren, wenn Sie diesen Bezeichner wörtlich verwenden wollen.) –

+1

Zeigen Sie uns, wie Sie sql_function_above 'in Ihrem Python-Code definiert haben. – nos

+0

Es war eine Vereinfachung von meiner Seite Ich habe versucht, die Variable auf verschiedene Arten zu schreiben. Ich habe auch versucht, den Text aus einer SQL-Datei zu lesen. Alle diese erzeugt den gleichen Fehler. Eine der vielen Möglichkeiten schrieb ich die Variable in die ursprüngliche Frage bearbeitet. PS Danke für alle Antworten - es ist das erste Mal, dass ich stackoverflow.com benutze und die Hilfsbereitschaft und Geschwindigkeit der Antworten von euch ist erstaunlich :) –

Antwort

28

standardmäßig psycopg2 Argument Platzhalter identifiziert das % Symbol (in der Regel würden Sie %s haben in der Zeichenfolge). Wenn Sie cursor.execute('... %s, %s ...', (arg1, arg2)) verwenden, werden die %s in die Werte von arg1 und arg2 umgewandelt.

Aber seit Sie anrufen: cursor.execute(sql_function_above), ohne zusätzliche Argumente, und Ihre SQL enthält % Zeichen die Bibliothek versucht zu finden, das zweite Argument in die Funktion übergeben - das ist außerhalb des Bereichs, daher ein IndexError.

Lösung: Anstatt % zu verwenden, schreiben Sie %% in Ihre SQL-Variable. Dies wird in ein Literal % übersetzt, bevor es an PostgreSQL gesendet wird.

1

Index außerhalb des Bereichs bedeutet, dass Sie versucht haben, auf das dritte Element eines Tupels zuzugreifen, das nur aus zwei Elementen besteht. Beachten Sie, dass Pythons Indizes bei 0 beginnen. Ein Tupel mit zwei Elementen namens "myTuple" würde also die Elemente myTuple [0] und myTuple [1], aber kein Element myTuple [2] enthalten.

+0

Ja ... das verwirrt mich umso mehr. Es hört sich an, als gäbe es ein Tupel in der psycopg2-Bibliothek Täter und das würde bedeuten, dass es einen Fehler in der psycopg2-Bibliothek gibt (oder spring ich zu den falschen Schlussfolgerungen?) Aber wenn ja, was ist das Besondere an meinem SQL, das eine Bibliothek bricht, die am meisten pe Finden Sie vollkommen stabil? Ein Teil des Problems hier ist, dass ich nicht einmal isolieren kann, wo genau die Dinge schief gehen, denn wenn ich versuche, das SQL außerhalb von Django auszuführen, erhalte ich keine Fehlermeldung und trotzdem wird das SQL nicht ausgeführt. –

+0

Ihr Code enthält Literalzeichen wie $ 2 und%. Einige Datenbankbibliotheken könnten thoe als Platzhalter für Parameter interpretieren. Im Python-Fall haben Sie die Transaktion wahrscheinlich nicht durchgeführt. – nos

3

Sieht aus wie Sie die Transaktion nicht begehen:

Try setzen:

 
cursor.execute("COMMIT") 

Nach der letzten Zeile und sehen, ob das funktioniert.

Sie auch die Isolationsstufe einstellen wie auf Autocommit:

 
connection.set_isolation_level(0) 

Weitere Informationen über die in diesem answer

+0

Obwohl der Tupelfehler nichts mit Transaktionen zu tun hatte, wurde die SQL-Funktion nach dem Entfernen des% -Zeichenproblems immer noch nicht geladen und dies war natürlich der Grund, also vielen Dank für diese Antwort auch :) –

+0

PS: Sie sollten 'connection.commit()' anstelle von "COMMIT" manuell verwenden - so kennt psycopg2 den aktuellen Transaktionszustand. – intgr

Verwandte Themen