Seite 1 von 1
mysql stored procedures
Verfasst: Freitag 13. Juni 2014, 22:07
von silver0346
Hallo zusammen,
ich versuche jetzt seit gefühlt 24 Stunden, einen Rückgabewert aus einer MySQL stored procedure in Python zu erhalten. Bisher habe ich stored procedures verwendet, die unter Perl zufriedenstellend laufen. Unter Python leider nicht. Deshalb habe ich das Beispiel von Oracle verwendet. Ist laut Website ziemlich einfach:
Code: Alles auswählen
CREATE PROCEDURE `sp1`(
in pStr1 varchar(20),
in pStr2 varchar(20),
out pConCat varchar(40)
)
BEGIN
set pConCat := CONCAT(pStr1, pStr2);
END
In Python:
Code: Alles auswählen
class DbTest(object):
def __init__(self):
super(DbTest, self).__init__()
def main(self):
config = {
'user': 'reporting',
'password': 'reporting',
'host': 'host',
'database': 'bla'
}
back = mysql.connector.connect(**config)
cur = back.cursor(buffered=True)
args = ('ham', 'spam', '')
cur.callproc('sp1', args)
print(cur.fetchone())
cur.close()
back.close()
if __name__ == '__main__':
m = DbTest()
m.main()
Ich kann den Vorgang im querry-log verfolgen:
Code: Alles auswählen
140613 22:28:12 87 Connect reporting@host on report
87 Query SET NAMES 'utf8' COLLATE 'utf8_general_ci'
87 Query SET @@session.autocommit = OFF
87 Query SET @_sp1_arg1='ham'
87 Query SET @_sp1_arg2='spam'
87 Query SET @_sp1_arg3=''
87 Query CALL sp1(@_sp1_arg1,@_sp1_arg2,@_sp1_arg3)
87 Query SELECT @_sp1_arg1,@_sp1_arg2,@_sp1_arg3
87 Quit
Wenn ich diese Zeilen in MySQL WorkBench kopiere, erhalte ich ein - erwartetes - Ergebnis. Nicht jedoch in Python: Hier ist das Ergebnis immer None.
Kann mir da jemand einen kleinen Denkanstoß geben?
Re: mysql stored procedures
Verfasst: Freitag 13. Juni 2014, 22:29
von BlackJack
Denkanstoss wäre die Dokumentation von `callproc()` zu konsultieren:
http://legacy.python.org/dev/peps/pep-0249/#callproc
Deine Prozedur stellt ja nichts bereit was man mit `fetchone()` auslesen könnte, sondern hat einen ``out``-Parameter.
Die Klasse ist übrigens unsinnig, da hätte es auch eine einfache Funktion getan. Und von `super()` würde ich die Finger lassen.
Re: mysql stored procedures
Verfasst: Samstag 14. Juni 2014, 07:37
von MagBen
Probier mal das
Code: Alles auswählen
args = ['ham', 'spam', ''] # eine list darf veraendert werden, ein tuple nicht
cur.callproc('sp1', args)
print(args) # eventuell ist in args[2] der out-Parameter
BlackJack hat geschrieben:Die Klasse ist übrigens unsinnig, da hätte es auch eine einfache Funktion getan.
In Java muss man das so machen.
Re: mysql stored procedures
Verfasst: Samstag 14. Juni 2014, 08:52
von Hyperion
MagBen hat geschrieben:
BlackJack hat geschrieben:Die Klasse ist übrigens unsinnig, da hätte es auch eine einfache Funktion getan.
In Java muss man das so machen.
Was hat Java damit zu tun :K Der OP sprach lediglich von Perl... und da braucht 's sicher auch keine Klasse

Re: mysql stored procedures
Verfasst: Samstag 14. Juni 2014, 09:29
von silver0346
Moin moin,
vielen Dank für die schnelle Antwort.
Mit dem Perl-Zitat wollte ich nur andeuten, dass die stored procedures funktionieren. Die Doku zu callproc kenne ich inzwischen wohl auswendig (ist ja auch nicht so lang). Ich habe mir sogar schon den Quelltext für das entsprechende Modul angesehen. Man kann ja nie wissen...
Wie aus dem query-log hervor geht, wird auf jeden Fall etwas für ein fetch*() bereitgestellt: Der letzte Befehl ist ein SELECT, der alle Parameter ausgibt (auch den gefüllten out-Parameter). In reinem SQL sieht man es. Nur sämtliche fetch-Varianten finden nichts. Auch der Vorschlag von MagBen bringt leider nicht den gewünschten Erfolg.
Und wieso ist super() böse?
Ich such mal noch ein wenig weiter...
Re: mysql stored procedures
Verfasst: Samstag 14. Juni 2014, 09:50
von BlackJack
Mal die beiden relevanten Sätze aus dem Dokument zu `callproc()`:
The result of the call is returned as modified copy of the input sequence. Input parameters are left untouched, output and input/output parameters replaced with possibly new values.
Und etwas später dann:
The procedure may also provide a result set as output. This must then be made available through the standard .fetch*() methods.
Was zusammengenommen IMHO ziemlich deutlich darauf hinweist, dass man sich mal den Rückgabewert der Methode anschauen sollte, und dass das auch eher der Regelfall gegenüber einem „result set” ist.
Zu `super()`:
Python's Super is nifty, but you can't use it. Mir ist das einfach zu kompliziert und ich habe es auch noch nie in eigenem Code *gebraucht*. Denn wirklich nützen tut das ja erst wenn man Mehrfachvererbung praktiziert die nicht aus ”Mixins” besteht. Und das macht meiner Erfahrung nach sowieso niemand.
Re: mysql stored procedures
Verfasst: Samstag 14. Juni 2014, 16:23
von MagBen
silver0346 hat geschrieben: Denn wirklich nützen tut das ja erst wenn man Mehrfachvererbung praktiziert die nicht aus ”Mixins” besteht.
Du brauchst super immer dann, wenn in der abgeleiteten Klasse das Verhalten der Parent-Klasse erweitert werden soll. Und wenn Du in Qt von einer QObject oder QWidget Klasse ableitest und im eigenen Konstruktor nicht super(..., self).__init__(...) aufrufst, dann funktioniert gar nichts mehr.
Re: mysql stored procedures
Verfasst: Samstag 14. Juni 2014, 16:36
von cofi
Die Alternative zu `super` ist nicht, dass man die Eltern-Methode gar nicht aufruft, sondern dass man es explizit tut. In dem Fall wuerde man eben `QObject.__init__(self, ...)` aufrufen.
Und bei quoten aufpassen, dass du auch den richtigen Autor triffst

Re: mysql stored procedures
Verfasst: Samstag 14. Juni 2014, 16:45
von BlackJack
@MagBen: Das stimmt so nicht denn man kann die entsprechende Methode der Basisklasse auch problemlos ohne `super()` aufrufen. `super()` ruft nicht die Methode der Basisklasse auf, sondern die nächste in der „method resolution order” (MRO). Das muss nicht die Methode in der Basisklasse sein. Denn wenn sie das immer wäre, dann gäbe es überhaupt keinen Grund für die Existenz der Funktion. Und ob man die nächste Methode in der MRO aufrufen muss, statt einfach nur die in der Basisklasse, hängt davon ab ob man sich irgendwelche spassigen „diamantförmigen” Vererbungsbeziehungen mittels Mehrfachvererbung gebastelt hat. So etwas mache ich nicht, und soweit ich bisher Python-Quelltext gesehen habe, macht das auch niemand anders der Wert auf seine geistige Gesundheit legt. Ergo: Wenn man keine Mehrfachvererbung abseits von ”Mixins” benutzt, ist die ganze Komplexität und die Konsequenzen die man sich mit `super()` einfängt, völlig unnötig.
Re: mysql stored procedures
Verfasst: Samstag 14. Juni 2014, 16:52
von MagBen
Hyperion hat geschrieben:Was hat Java damit zu tun
Keine Ahnung warum dieses Problem etwas mit Java zu tun hat. Mir ist lediglich aufgefallen, dass da jemand Python wie Java programmiert.
Re: mysql stored procedures
Verfasst: Samstag 14. Juni 2014, 17:01
von MagBen
BlackJack hat geschrieben:Wenn man keine Mehrfachvererbung abseits von ”Mixins” benutzt, ist die ganze Komplexität und die Konsequenzen die man sich mit `super()` einfängt, völlig unnötig.
Ich finde super nicht besonders komplex. Ich habe es in Java sehr gerne benutzt und ich vermisse es in C++.
super() ist immer dann super, wenn sich die Vererbunghierarchie im Lauf der Zeit entwickelt. Klasse C wird von Klasse A abgeleitet, ein Jahr später fummele ich da noch eine Klasse B dazwischen, sodass C von B und B von A abgeleitet ist. Mit super ruft C in der ersten Version Klasse A auf und später dann Klasse B. Hätte ich Klasse A in C explizit aufgerufen, dann würde ich mich später wundern, warum meine Klasse B keine Auswirkung hat.
Re: mysql stored procedures
Verfasst: Samstag 14. Juni 2014, 17:11
von silver0346
Wieder zurück.
Ich kann gar nicht java-Programmierung. Das Einzige, was mir - mit Google und Co. - gelingt ist Perl. Jetzt versuche ich mich an Python, indem ich bisher als Perl-Scripte laufende Sachen umschreibe. Unter anderem, weil ich recht leicht eine GUI zusammenklöppeln kann. Unter Perl war da etwas mehr Aufwand nötig. Aber zurück zum Thema:
Ich habe etwas im Quelltext probiert. Dabei ist mir folgendes aufgefallen: In cursor.py lautet das Original in callproc:
Code: Alles auswählen
if argnames:
select = "SELECT {0}".format(','.join(argtypes))
self.execute(select)
self._stored_results = results
return self.fetchone()
else:
self._stored_results = results
return ()
Dabei kommt nichts zurück. Ersetze ich jedoch fetchone() durch fetchall()[0] kriege ich ein Tupel mit genau den Werten, die ich haben will.
Und da ich weiß, an welcher Stelle mein Rückgabewert stehen soll, kann ich mit
auf die Zelle zugreifen. Ich habe zwar noch nicht probiert, ob es in allen Fällen zufriedenstellend funktioniert, aber es scheint der richtige Weg zu sein. Warum fetchone() nichts liefert ist mir noch nicht ganz klar. Komme ich aber noch hinter.
