Question

J'utilise Python avec adodbapi de pywin32 pour écrire un script pour créer une base de données SQL Server et toutes ses tables associées, des vues et des procédures. Le problème est que la DBAPI Python exige que cursor.execute () être enveloppé dans une transaction qui ne commise par cursor.commit (), et vous ne pouvez pas exécuter une goutte ou create base de données dans une transaction utilisateur. Toutes les idées sur la façon de contourner cela?

EDIT:

Il ne semble pas être quelque chose d'analogue à un paramètre autocommit soit la méthode connect () de adodbapi ou la méthode du curseur (). Je serais heureux d'utiliser pymssql au lieu de adodbapi, sauf qu'il tronque types de données char et varchar à 255 caractères.

Je l'ai fait essayer avant de poster; voici le retraçage.

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
Était-ce utile?

La solution

L'objet connexion adodbapi ne démarre pas automatiquement conn une nouvelle transaction après chaque commit si la base de données prend en charge les transactions. DB-API nécessite la validation automatique à désactivé par défaut et permet une méthode API pour le rallumer, mais je ne vois pas un dans adodbapi.

Vous pourriez être en mesure d'utiliser la propriété de pirater conn.adoConn autour de cela, en utilisant l'api ADO à la place de l'API DB-vous sortir de toute transaction. Faites-moi savoir si cela fonctionne:

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

Voici la source de la adodbapi méthode commit () .

Autres conseils

« Le problème est que la DBAPI Python exige que cursor.execute () être enveloppé dans une transaction qui ne commise par cursor.commit () »

« et vous ne pouvez pas exécuter une goutte ou create base de données dans une transaction utilisateur. »

Je ne suis pas sûr que tout cela est effectivement vrai pour toutes les interfaces DBAPI.

Puisque vous ne présentez pas les messages d'erreur, il peut arriver que ce n'est pas vrai pour l'interface ADODBAPI. Avez-vous déjà essayé? Si oui, quel message d'erreur vous obtenez?

Une connexion ne peut pas toujours à créer une "transaction utilisateur". Vous pouvez les connexions souvent ouvertes pour obtenir avec autocommit=True autocommit style LDD.

, vous pouvez également envisager d'utiliser une autre connexion pour faire courir DDL.

http://pymssql.sourceforge.net/ par exemple, en cours d'exécution montre DDL comme celui-ci.

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

créer la db réelle en dehors de la transaction. Je ne suis pas familier avec python, mais il doit y avoir un moyen d'exécuter une chaîne donnée utilisateur sur une base de données, l'utilisation que la commande réelle créer db. Utilisez ensuite le adodbapi faire toutes les tables, etc et valider cette transaction.

J'ai eu ce même problème en essayant d'exécuter des commandes sur adodbapi (par exemple DBCC CHECKDB ...) et les conseils de joeforker aidé un peu. Le problème que j'avais encore été que adodbapi démarre automatiquement une transaction, donc il n'y avait aucun moyen d'exécuter quelque chose en dehors d'une transaction.

En fin de compte, je fini par désactiver Commit années adodbapi comme ceci:

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

Pour autant que je peux dire, ce nouveau standard permet la fonctionnalité auto-validation SQL Server, à savoir chaque instruction SQL est automatiquement engagée. L'inconvénient est qu'il n'y a aucun moyen pour moi de transactions ont permis à nouveau (pour le moment) si je wan't pour exécuter quelque chose dans une transaction, puisque ne fait rien Connection.commit() quand supportsTransactions == False.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top