Domanda

Sto usando Python con adodbapi di pywin32 scrivere uno script per creare un database di SQL Server e di tutte le sue tabelle associate, viste e procedure. Il problema è che DBAPI di Python richiede che cursor.execute () essere avvolto in una transazione che si impegna solo da cursor.commit (), e non è possibile eseguire una goccia o creare un'istruzione di database in una transazione utente. Tutte le idee su come ottenere intorno a questo?

EDIT:

Non sembra essere nulla di analogo a un parametro autocommit sia al metodo connect () di adodbapi o il suo metodo di cursore (). Sarei felice di usare pymssql invece di adodbapi, tranne che tronca char e varchar tipi di dati a 255 caratteri.

Ho provato questa prima dell'inserimento; ecco la traceback.

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
È stato utile?

Soluzione

L'oggetto di connessione adodbapi conn si avvia automaticamente una nuova transazione dopo ogni commit se il database supporta le transazioni. DB-API richiede autocommit per essere disattivata per default e permette un metodo API per riaccenderlo, ma non vedo uno in adodbapi.

Si potrebbe essere in grado di utilizzare il conn.adoConn proprietà per incidere intorno a questo, utilizzando l'API ADO invece di DB-API per portarvi fuori di ogni transazione. Fatemi sapere se questo funziona:

conn.adoConn.CommitTrans()
cursor.execute('CREATE DATABASE ...')
conn.adoConn.BeginTrans()

Ecco il sorgente per il adodbapi commit () metodo .

Altri suggerimenti

"Il problema è che DBAPI di Python richiede che cursor.execute () essere avvolto in una transazione che si impegna solo da cursor.commit ()"

"e non si può eseguire una goccia o creare un'istruzione di database in una transazione utente."

Non sono sicuro che tutto questo è in realtà vale per tutte le interfacce DBAPI.

Dal momento che non si mostra i messaggi di errore, può risultare che questo non è vero per l'interfaccia ADODBAPI. Hanno effettivamente provato? Se sì, quale messaggio di errore vuoi arrivare?

Una connessione non può sempre essere la creazione di una "transazione utente". È possibile connessioni spesso aperti con autocommit=True per arrivare in stile DDL autocommit.

Inoltre, si potrebbe voler considerare l'utilizzo di una connessione di diverso da fare run DDL.

http://pymssql.sourceforge.net/ per esempio, mostra DDL in esecuzione simili.

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))')

creare il db reale al di fuori della transazione. Non ho familiarità con Python, ma ci deve essere un modo per eseguire un utente data stringa su un database, l'uso che con l'attuale comando di db creare. Quindi utilizzare l'adodbapi per fare tutti i tavoli, ecc e si impegnano tale operazione.

Ho avuto questo stesso problema durante il tentativo eseguire comandi oltre adodbapi (ad esempio DBCC CHECKDB ...) e la consulenza di joeforker aiutato un po '. Il problema che ho avuto è stato ancora che adodbapi avvia automaticamente una transazione, quindi non c'era modo di eseguire qualcosa al di fuori di una transazione.

Alla fine ho finito per la disattivazione adodbapi di commettere un comportamento come questo:

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

Per quanto posso dire, questa ri-abilita l'auto-commit funzionalità, vale a dire ogni istruzione SQL standard di SQL Server si impegna automaticamente. Lo svantaggio è che non c'è modo per me di transazioni attivate di nuovo (al momento) se mi wan't di eseguire qualcosa all'interno di una transazione, in quanto Connection.commit() farà nulla quando supportsTransactions == False.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top