Ein kleines Beispiel für ODBC am Beispiel von MS Access.

Code-Stücke können hier veröffentlicht werden.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Also das mit dem COMMIT war wohl quatsch... Das ist nur bei 'Transaction' notwendig...

Aber irgendwie kommt mir das alles komisch vor:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import cgitb;cgitb.enable()

print "Content-type: text/html; charset=utf-8\r\n"

import adodbapi as dbapi


DSN_info = (
    "DRIVER=SQL Server;"
    "SERVER=.\SQLEXPRESS;"
    "DATABASE=DatabaseName;"
    "UID=UserName;"
    "PASSWORD=Password;"
)


class test:
    def __init__( self ):
        print "<pre>"
        self.connect()
        self.make_test_table()
        self.select_all()

        self.insert_1()
        self.select_all()

        self.delete_1()
        self.select_all()

        self.delete_test_table()
        self.close()
        print "</pre>"

    def connect(self):
        print "connect:",
        print DSN_info

        try:
            self.connection = dbapi.connect(DSN_info)
            self.cursor = self.connection.cursor()
        except Exception, e:
            print "Error:", e
            sys.exit()
        else:
            print "Connection OK"

    def close(self):
        self.connection.close()
        print "\n\nConnection closed"

    def make_test_table(self):
        SQLcommand  = (
            "CREATE TABLE TestTable ("
            "id INTEGER NOT NULL PRIMARY KEY IDENTITY(1,1), "
            "data1 VARCHAR( 50 ) NOT NULL, "
            "data2 VARCHAR( 50 ) NOT NULL"
            ");"
        )

        self.execute(
            "Creat a temporary test table",
            SQLcommand
        )

    def delete_test_table(self):
        self.execute(
            "Delete temporary test table",
            "DROP TABLE TestTable;"
        )

    def insert_1(self):
        self.execute(
            "RAW INSERT without SQLescaping",
            "INSERT INTO TestTable (data1,data2) VALUES ('Value A 1', 'Value A 2');"
        )

    def select_all(self):
        result = self.fetchall(
            "SELECT all",
            "SELECT * FROM TestTable;"
        )
        print result

    def delete_1(self):
        self.execute(
            "RAW DELETE values",
            "DELETE FROM TestTable WHERE data1='Value A 1';"
        )

    def execute(self, comment, SQLcommand):
        print "\n\n%s:" % comment
        print "SQLcommand:", SQLcommand
        try:
            self.cursor.execute(SQLcommand)
        except Exception, e:
            print "Error:", e
        else:
            print "OK"

    def fetchall(self, comment, SQLcommand):
        print "\n\n%s:" % comment
        print "SQLcommand:", SQLcommand
        try:
            self.cursor.execute(SQLcommand)
            return self.cursor.fetchall()
        except Exception, e:
            print "Error:", e
        else:
            print "OK"



if __name__ == "__main__":
    test()
Ich lasse doch einfach nur ein paar SQL-Befehle ablaufen. Dennoch kommt es zu dem Fehler:
Mehrfache Recordsets sind bei einer Transaktion mit diesem Cursortyp nicht m\xf6glich. \xc4ndern Sie entweder den Cursortyp, f\xfchren Sie Commit f\xfcr die Transaktion aus, oder schlie\xdfen Sie eines der Recordsets.
Aber je nachdem welche Befehle ich ausführe kommt das mal früher oder später. Irgendwie sehe ich da keinen Zusammenhang :?

Etwas komisch ist es auch wenn ich mit CREATE TABLE und DROP TABLE rumspiele... Man kann CREATE TABLE immer wieder ausführen und es kommt zu keinem Fehler?!?!?

Kann es sein, das es da irgendie ein Cache Mechanismus gibt?!?!


EDIT: So, nun hab ich genau die gleiche Aktion mit ODBC gemacht und damit klappt alles einwandfrei!!! Also ist ADOBDAPI mist???

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

jens hat geschrieben:Also das mit dem COMMIT war wohl quatsch... Das ist nur bei 'Transaction' notwendig...
[...]
Ich lasse doch einfach nur ein paar SQL-Befehle ablaufen. Dennoch kommt es zu dem Fehler:
Mehrfache Recordsets sind bei einer Transaktion mit diesem Cursortyp nicht m\xf6glich. \xc4ndern Sie entweder den Cursortyp, f\xfchren Sie Commit f\xfcr die Transaktion aus, oder schlie\xdfen Sie eines der Recordsets.
Aber je nachdem welche Befehle ich ausführe kommt das mal früher oder später. Irgendwie sehe ich da keinen Zusammenhang :?

Etwas komisch ist es auch wenn ich mit CREATE TABLE und DROP TABLE rumspiele... Man kann CREATE TABLE immer wieder ausführen und es kommt zu keinem Fehler?!?!?
Kann es sein, das es da irgendie ein Cache Mechanismus gibt?!?!
Hi Jens!

So wie ich das sehe, ignorierst du die Transaktionen. Wahrscheinlich wird vor jeder Abfrage automatisch ein "Begin Transaction" ausgeführt. Was kein Problem ist, wenn du nur ein paar Daten abfragst, aber es ist definitiv ein Problem, wenn du etwas in der Datenbank veränderst. Du musst wahrscheinlich nach jeder SQL-Anweisung, die etwas in der Datenbank verändert, ein adodb.commit, db.commit oder cursor.commit oder etwas ähnliches ausführen. Erst dann ist die Transaktion abgeschlossen -- die Änderung akzeptiert.

Wenn du eine Tabelle erstellst und noch im gleichen Prozess, die Tabelle füllst und abfragst, dann könnte es sein, dass du den Inhalt der Tabelle auslesen kannst. Wartest du aber eine Sekunde und möchtest dann noch einmal den Inhalt der Tabelle abfragen, dann ist nichts mehr da, was du abfragen könntest. Die Änderung wurde ja nicht mit "Commit Transaction" oder einem anderen, an die Connection gebundenen Befehl, abgeschlossen.

SQLite z.B. hält sich auch daran, dass es Änderungen nur nach einem "Commit Transation" akzeptiert. Und AutoCommit sollte man sowiso nicht einschalten, da das Datenbanksystem dadurch hergebremst wird.

Dass man "Create Table" immer wieder ausführen kann, sehe ich als Indiz für meine Theorie an. Natürlich kann man immer wieder die gleiche Tabelle erstellen, wenn der Erstellvorgang niemals korrekt abgeschlossen wurde.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dann ist bei MySQLdb und ODBC immer AutoCommit eingeschaltet???

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

jens hat geschrieben:Dann ist bei MySQLdb und ODBC immer AutoCommit eingeschaltet???
Hi Jens!

Bei MySQL weiß ich gar nicht, ob es so etwas wie ein Transaktionsmanagement überhaupt gibt.

ODBC hält sich aus so etwas raus. Es leitet einfach nur die SQL-Anweisungen weiter.

Als Standard-Einstellung von MS-SQL steht "AutoCommit" auf "Ein". Wenn man trotzdem mit ADODBAPI ein Commit nachschicken muss, dann mischt sich ADODBAPI ein.

Tut es auch. Ich habe soeben im Quelltext von ADODBAPI nachgesehen.

Code: Alles auswählen

if self.supportsTransactions:
    self.adoConn.IsolationLevel=defaultIsolationLevel
    self.adoConn.BeginTrans() #Disables autocommit
lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Danke für deine Hilfe!!!

Also ich hab es jetzt nochmal mit adodbapi probiert. Wenn ich immer ein connection.commit() mache, kommt es wieder zu einem Fehler:
Die Transaktion kann im Firehosemodus nicht gestartet werden

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

jens hat geschrieben: Wenn ich immer ein connection.commit() mache, kommt es wieder zu einem Fehler:
Die Transaktion kann im Firehosemodus nicht gestartet werden
Hi Jens!

Den **Firehosemodus** kenne ich noch nicht, das muss in der 2005'er Version neu eingeführt worden sein. Die Fehlermeldung ist auf deutsch. Da es im ADODBAPI keine deutschen Fehlermeldungen gibt, muss diese direkt vom SQL-Server kommen. Da im ADODBAPI auch kein besonderer Modus ausgewählt wird, dürfte das jetzt der Standardmodus für ADODB-Abfragen sein.
Wie auch immer -- mehr habe ich dazu nicht beizutragen. Ich möchte mich ja von MS-Datenbanken zurück ziehen, weil ich keinen Mehrwert mehr in der Verwendung dieser Technologie sehe.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Na, also ich möchte auch kein MSSQL Experte werden... Nur, weil es ja eine Anbindung gibt die ja fast die selbe ist (Python DB-API) wäre es doch schade, wenn ich nicht auch MSSQL unterstützen würde ;) Zumal ich es im konkreten Fall auch brauche ;)

Ich möchte gern generell an der "portierbarkeit" zur SQL-DB arbeiten um MySQL, SQLite (interessant für eine Standalone-Probier-Variante) und MSSQL unterstützen zu können.

Naja, ich denke da werde doch für MSSQL doch auf ODBC setzten, weil das andere einfach zuviele Probleme macht. Schade eigentlich...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Unterstützt nicht auch SQLObject MSSQL?
TUFKAB – the user formerly known as blackbird
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Hm! Das tut es wohl:
Currently SQLObject supports MySQL via MySQLdb aka MySQL-python, PostgreSQL via psycopg, SQLite via PySQLite, Firebird via kinterbasdb, Sybase via Sybase, and MAX DB (also known as SAP DB) via sapdb, MSSQL Server via pymssql (+ FreeTDS) or ADODBAPI (Win32).
Allerdings müßte ich dann schon komplett auf SQLObject übersatteln... Aber das dürfte wesendlich mehr Arbeit sein... Auf langer sicht gesehen, ist SQLObject schon interessant, aber das muß ich mir halt nochmal näher anschauen.

Ich denke ich mach erstmal mit win32/ODBC weiter...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten