Erstellen einer SQL Server-Datenbank von Python
-
21-08-2019 - |
Frage
Ich verwende Python mit pywin32 des adodbapi ein Skript zu schreiben, um eine SQL Server-Datenbank zu erstellen und alle zugehörigen Tabellen, Views und Prozeduren. Das Problem ist, dass Python DBAPI erfordert, dass cursor.execute () in einer Transaktion eingewickelt werden, die nur durch cursor.commit begangen wird (), und Sie können keinen Tropfen oder erstellen Datenbank-Anweisung in einer Benutzertransaktion auszuführen. Alle Ideen, wie um das zu bekommen?
EDIT:
Es scheint nicht zu etwas analog zu einem autocommit Parameter entweder die connect () -Methode von adodbapi oder dessen Cursor () -Methode. Ich würde gerne pymssql verwenden, anstatt adodbapi, mit der Ausnahme, dass es char und varchar-Datentypen auf 255 Zeichen abschneidet.
habe ich versuchen, dies vor der Veröffentlichung; hier ist die Rückverfolgung.
Traceback (most recent call last):
File "demo.py", line 39, in <module>
cur.execute("create database dummydatabase")
File "C:\Python26\lib\site-packages\adodbapi\adodbapi.py", line 713, in execute
self._executeHelper(operation,False,parameters)
File "C:\Python26\lib\site-packages\adodbapi\adodbapi.py", line 664, in _executeHelper
self._raiseCursorError(DatabaseError,tracebackhistory)
File "C:\Python26\lib\site-packages\adodbapi\adodbapi.py", line 474, in _raiseCursorError
eh(self.conn,self,errorclass,errorvalue)
File "C:\Python26\lib\site-packages\adodbapi\adodbapi.py", line 60, in standardErrorHandler
raise errorclass(errorvalue)
adodbapi.adodbapi.DatabaseError:
--ADODBAPI
Traceback (most recent call last):
File "C:\Python26\lib\site-packages\adodbapi\adodbapi.py", line 650, in _executeHelper
adoRetVal=self.cmd.Execute()
File "<COMObject ADODB.Command>", line 3, in Execute
File "C:\Python26\lib\site-packages\win32com\client\dynamic.py", line 258, in _ApplyTypes_
result = self._oleobj_.InvokeTypes(*(dispid, LCID, wFlags, retType, argTypes) + args)
com_error: (-2147352567, 'Exception occurred.', (0, u'Microsoft SQL Native Client', u'CREATE DATABASE statement not allowed within multi-statement transaction.', None, 0, -2147217900), None)
-- on command: "create database dummydatabase"
-- with parameters: None
Lösung
Das adodbapi Verbindungsobjekt conn
startet automatisch eine neue Transaktion nach jedem Commit, wenn die Datenbank Transaktionen unterstützt. DB-API autocommit erfordert standardmäßig deaktiviert werden und ermöglicht eine API-Methode, um es wieder einzuschalten, aber ich sehe nicht ein in adodbapi.
könnten Sie in der Lage sein, die conn.adoConn
Eigenschaft zu verwenden, um dies zu hacken, die ADO api statt DB-API verwenden Sie aus jeder Transaktion zu übernehmen. Lassen Sie mich wissen, ob das funktioniert:
conn.adoConn.CommitTrans()
cursor.execute('CREATE DATABASE ...')
conn.adoConn.BeginTrans()
Hier ist die Quelle für die adodbapi commit () -Methode .
Andere Tipps
"Das Problem ist, dass Python DBAPI erfordert, dass cursor.execute () in einer Transaktion eingewickelt werden, die nur durch cursor.commit () begangen wird"
„und Sie können keinen Tropfen ausführen oder Datenbank-Anweisung in einer Benutzertransaktion erstellen.“
Ich bin nicht sicher, ob all dies für alle DBAPI Schnittstellen tatsächlich wahr ist.
Da Sie nicht die Fehlermeldungen zeigen, kann es sich herausstellen, dass dies für ADODBAPI Schnittstelle ist nicht wahr. Haben Sie es wirklich versucht? Wenn ja, welche Fehlermeldung erhalten Sie?
Eine Verbindung kann nicht immer eine "Benutzertransaktion" erschaffen. Sie können oft offene Verbindungen mit autocommit=True
DDL-Stil autocommit zu erhalten.
Auch möchten Sie vielleicht eine andere Verbindung zu prüfen, unter Verwendung einer Lauf DDL zu tun.
http://pymssql.sourceforge.net/ zeigt zum Beispiel DDL wie diese ausgeführt wird.
import pymssql
conn = pymssql.connect(host='SQL01', user='user', password='password', database='mydatabase')
cur = conn.cursor()
cur.execute('CREATE TABLE persons(id INT, name VARCHAR(100))')
die tatsächliche db außerhalb der Transaktion erstellen. Ich bin nicht vertraut mit Python, aber es muss ein Weg sein, um einen Benutzer angegebene Zeichenfolge auf einer Datenbank ausführen, verwenden Sie das mit der db Befehl tatsächlich erstellen. Dann die adodbapi verwenden, um alle Tabellen zu tun, etc. und diese Transaktion verpflichten.
Ich hatte das gleiche Problem, während Ausführen von Befehlen über adodbapi versuchen (z DBCC CHECKDB ...) und Rat des joeforker ein wenig geholfen. Das Problem, das ich noch hatte, dass adodbapi startet automatisch eine Transaktion, so dass es keine Möglichkeit, etwas außerhalb einer Transaktion auszuführen.
Am Ende landete ich deaktivieren adodbapi Verhalten wie diese begehen:
self.conn = adodbapi.connect(conn_str)
# rollback the transaction that was started in Connection.__init__()
self.conn.adoConn.RollbackTrans()
# prevent adodbapi from trying to rollback a transaction in Connection.close()
self.conn.supportsTransactions = False
Soweit ich sagen kann, diese wieder aktiviert die Standard-SQL Server autocommit Funktionalität, das heißt jede SQL-Anweisung automatisch festgelegt wird. Der Nachteil ist, dass es für mich keine Möglichkeit, wieder zu aktivieren, damit Transaktionen (im Moment), wenn ich etwas innerhalb einer Transaktion ausführen wan't, da Connection.commit()
nichts tun wird, wenn supportsTransactions == False
.