stored procedure mit updates macht nichts?

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

Hallo Leute,

ich habe da mal wieder ein Problem.
Ich habe für mein Python-Projekt ein Stored Procedure in meiner MySQL-DB eingerichtet.
Dieses Prozedur beinhaltet viele hochkomplexe Update-Befehle und dauert auch ein paar Sekunden bis die abgearbeitet werden (~20 s).

Mein Problem ist nun wie folgt:
Diese Stored-Procedure verrichtet sein Dienst tadellos in der MySQL-Worbench (eine MySQL-GUI). Ich überprüfe die Resultate nach dem Ablauf und tatsächlich wurde alles gemacht was gemacht werden sollte.

So, nun möchte ich diese Stored-Procedure aus meinem Python-Programm aufrufen.
Zuerst habe ich mit Permission denied herumgekämpft. Kurz recherchiert, Berechtigungen auf den User vergeben der bemängelt wurde (als Error-Meldung in der Konsole und dieser ist es natürlich auch mit dem ich das Programm an der DB anmelde) und danach waren keine Fehler mehr vorhanden.
Er wartet auch ca. 20s bis diese Stored-Procedure abgearbeitet wurde und beendet das Programm dann tadellos.
Bei der Prüfung der Daten stellt sich aber heraus das gar nichts gemacht worden ist!

Wie gesagt: an der Procedure kann es nicht liegen denn wenn ich diese in der DB-Oberfläche aufrufe (call MyProcedure();) dann funktioniert es auch.

Hier wie ich die Procedure aus Python aufrufe (habe ich so bei 'stackoverflow' gefunden):
objDB.cursor.callproc('MyProcedure')
objDB.cursor.execute("SELECT @MyProcedure;")

So, ich vermute mal daß ich a) nicht beide so aufrufen muss und das alleine 'callproc' ausreichen müsste und b) das in einem der beiden, wen nicht gar in beiden, falsch angehe.

'objDB' instanziere ich zuvor und lasse diese per Konstruktor mit der DB verbinden. In meinen hunderten anderen SQL-Statements (Selects, Inserts & Updates) funktioniert diese vorgehensweise auch bei der gleichen Klasse.
Ich habe es mit und ohen 'commit' probiert (weil ich nicht sicher bin ob commit bei einer Stored Procedure von Nöten ist oder nicht (oder es sogar stört).

So, kann mir einer hier helfen und erklären was man bei stored procedures genau beachten muss damit es funktioniert?

Ich bedanke mich schon einmal im Voraus für eure Hilfe!
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

richtig `callproc()` sollte reichen. Deine Stored Procedure erwartet aber keine weiteren Parameter, d.h. anstoßen reicht, alle Werte werden aus der DB gezogen?

Welches Modul verwendest du zur Anbindung von MySQL?

Gruß, noisefloor
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

@noisefloor

Genau. Die Stored Procedure erwartet keine Parameter.
Die Updatewerte werden teils aus anderen Tabellen oder fixen Werten genommen. Ebenso die Bedingungen. Es sind 'in sich geschlossene Abfragen' die lediglich aufgerufen werden müssen.

Es sind ca. 7 Updatebefehle enthalten die teils wirklich hochkomplex sind. Jede dieser Updatebefehle wird mit einem Semikolon abgeschlossen.
Den Delimiter am Anfang und Ende habe ich einmal als Semikolon belassen (Default) und auch einmal als doppeltes Dollarzeichen gesetzt um die Stored-Prozeduren-Befehle abzugrenzen (wobei die Updatebefehle nach wie vor mit Semikolon abgeschlossen wurden). In beiden Fällen (DELIMITER DEFUALT & $$) konnte ich die Prozedure aufrufen und ausführen in der MySQL-GUI. In beiden Fällen ging es aus meinen Python-Programmen nicht.

Welches Modul ich für die MySQL verwende? Uff, muss ich heute Abend in meine MySQL-Klasse reinschauen. Wenn es ein einfaches und viele komplexere 'Modelle' gibt habe ich sicherlich das Standard und Einfache gewählt... Wenn dir das zu vage ist -> ich schaue heute Abend und sage es dann genau... Ist das wichtig? Gibt es da verschiedene Herangehensweisen? Wenn es syntaktisch falsch wäre, würde Python ja meckern, oder? Die anderen 'normalen' inserts, updates usw. funktionieren jedenfalls..

Wie o.g. hat Python erst die fehlende Berechtigung für diese Prozedur bemängelt. Das habe ich aber mittlerweile gelöst.

Was vielleicht auch noch sein kann:
Ich habe in der Stored Procedure auch Kommentare die jeweils mit '#' auskommentiert wurden. Könnte es vielleicht sein das je nach Anbindung an die DB die Kommentare bei einem stören und beim anderen nicht? Aber dann würde Python das ja 'anmekern' mit diversen Fehlermeldungen, oder?
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Hast du die Möglichkeit, deine Datenbank die Ausführung aller Befehle loggen zu lassen, wenn deine SP aus Python heraus aufgerufen wird? Vielleicht fehlt ja die Berechtigung zum Schreiben der Änderungen und Python reicht die entsprechende Mitteilung nicht weiter...?
Benutzeravatar
noisefloor
User
Beiträge: 3843
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Ist das wichtig? Gibt es da verschiedene Herangehensweisen?
Für MySQL gibt es eine Reihe von Modulen. Theoretisch sollte es egal sein, welches man nimmt, weil das `callproc() in der Python DB API 2.0 / PEP-0249 definiert ist.
Praktisch könnte es aber sein, dass das Modul da sein eigenes Süppchen kocht, buggy ist oder vielleicht auch die DB API 2.0 nicht vollständig unterstützt.

Gruß, noisefloor
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

@snafu

Da es bisher lediglich in der Testumgebung auf meinen virtuellen Maschinen läuft, kann ich es sicherlich mitloggen lassen wenn ich wüsste welche Config-Datei ich wie ändern müsste? Das muss ich ja dann aussschliesslich auf dem MySQL-Server machen und andere 'Systeme' sind aussen vor, richtig?
Ich sage das nur weil ich einen separaten MySQL-Server habe auf den dann meine VB.NET (von meinem Haupt Windows-Arbeitsrechner), PHP (von meinem Webserver Apache2 als separate VM) und Python (von einer anderen separaten VM)-Programme zugreifen. Ich habe also kein LAMP oder der Gleichen.

@noisefloor
ich schaue heute Abend dann noch mal nach welches MySQL-Paket ich in diesem Projekt importiere und benutzte.
(ich habe es soeben per VPN & SSH vom Handy versucht. Merke aber gerade das ich nur auf meinen Haupt-Ubuntu-Server, den Fileserver komme... habe wohl vergessen den Zugriff von Any zu erlauben...)
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Du hast da nicht zufällig eine (implizite) Transaction die du nicht comittest?
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

@noisefloor

Ich importiere die 'MySQLdb' in meine MySQL-Klasse. Somit ist es das was ich nutze um mich mit der DB zu verbinden.

@DasIch
Du hast da nicht zufällig eine (implizite) Transaction die du nicht comittest?
Ich mache eigentlich nur das was ich oben gepostet habe. Habe ein Commit eine Zeile später gesetzt und mit Commit als auch ohne verändert sich in meiner DB nichts..
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

@DasIch

Du hast mich auf die Idee gebracht mir nochmals das mit dem Commit anzuschauen.
Und ich habe bemerkt das ich an dieser Stelle doch ein Fehler gemacht habe, welchen mir Python komischerweise nicht mit einem Fehler quittiert hat (was es doch sonst bei jeder Kleinigkeit macht).
Ich habe ein Commit auf dem Cursor gehabt statt auf die DB! Kaum habe ich es umgeändert hat es dann auch geklappt!

Also wenn mein Objekt der Klasse MySQLdb objSQL heisst dann habe ich folgendes gemacht:

Code: Alles auswählen

objSQL.cursor.callproc("myProcedure")
objSQL.cursor.commit()
Richtig wäre es ja wie folgt:

Code: Alles auswählen

objSQL.cursor.callproc("myProcedure")
objSQL.db.commit()
In meiner MySQL-Klasse, welche wiederrum die MySQLdb enthält (die alles updates, inserts und selects für mich übernimmt und gleich das Commit mitübergibt) mache ich alles richtig. Jetzt habe ich mich in dem Aufruf der SP irreleiten lassen und das Commit eben an dne Cursor gehängt. Mist, und dafür habe ich nun so viele Beiträge benötigt.... das wurmt mich... sorry Leute.
Dafür weiß ich jetzt das ein callproc("myProcedure") + commit reicht um die SP aufzurufen ;))
Antworten