Pregunta

Estoy usando Python con adodbapi de pywin32 para escribir un script para crear una base de datos de SQL Server y todas sus tablas asociadas, vistas y procedimientos. El problema es que DBAPI de Python requiere que cursor.execute () ser envuelto en una transacción que sólo se ha comprometido por cursor.commit (), y no se puede ejecutar una gota o sentencia de creación de base de datos en una transacción de usuario. Cualquier ideas sobre cómo conseguir alrededor de eso?

EDIT:

No parece ser algo análogo a un parámetro de confirmación automática ya sea al método connect () de adodbapi o su método de cursor (). Yo estaría feliz de usar pymssql en lugar de adodbapi, excepto que trunca char y varchar tipos de datos a 255 caracteres.

Yo probé esto antes de la publicación; aquí está el rastreo.

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
¿Fue útil?

Solución

El objeto de conexión adodbapi conn se inicia automáticamente una nueva transacción después de cada confirmación, si la base de datos compatible con las transacciones. DB-API requiere confirmación automática a ser desactivada por defecto y permite un método de API para volver a encenderla, pero no veo una en adodbapi.

Usted puede ser capaz de utilizar el conn.adoConn propiedad de cortar alrededor de esto, el uso de la API de ADO en lugar de DB-API para llevarlo a cabo de cualquier transacción. Déjame saber si esto funciona:

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

Aquí está la fuente de la adodbapi commit () método .

Otros consejos

"El problema es que DBAPI de Python requiere que cursor.execute () ser envuelto en una transacción que sólo se ha comprometido por cursor.commit ()"

"y no puede ejecutar una gota o sentencia de creación de base de datos en una transacción de usuario."

No estoy seguro de que todo esto es realmente cierto para todas las interfaces DBAPI.

Dado que no se presentan los mensajes de error, que puede resultar que esto no es cierto para la interfaz ADODBAPI. ¿Realmente lo has intentado? Si es así, ¿qué mensaje de error te va?

Una conexión no puede siempre ser la creación de una "transacción de usuario". Puede conexiones abiertas con frecuencia autocommit=True para obtener la confirmación automática de estilo DDL.

Además, es posible que desee considerar el uso de una conexión diferente para hacer carrera DDL.

http://pymssql.sourceforge.net/ por ejemplo, muestra DDL siendo ejecutado como este.

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

crear la db real fuera de la transacción. No estoy familiarizado con Python, pero tiene que haber una manera de ejecutar un usuario determinado cadena en una base de datos, el uso real que con el comando create db. A continuación, utilice el adodbapi para hacer todas las mesas, etc., y cometer esa transacción.

Tuve este mismo problema al intentar ejecutar comandos más adodbapi (por ejemplo DBCC CHECKDB ...) y el consejo de joeforker ayudado un poco. El problema que todavía tenía era que adodbapi inicia automáticamente una transacción, así que no había manera de ejecutar algo fuera de una transacción.

Al final me terminó la desactivación de adodbapi comprometen el comportamiento de esta manera:

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

Por lo que yo puedo decir, este vuelve a habilitar la funcionalidad de confirmación automática, es decir, cada sentencia SQL estándar de SQL Server se ha comprometido de forma automática. La desventaja es que no hay manera para que las transacciones habilitadas de nuevo (por el momento) si me wa no a ejecutar algo dentro de una transacción, ya que Connection.commit() no hará nada cuando supportsTransactions == False.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top