Вопрос

Я использую Python с adodbapi pywin32 для написания сценария для создания базы данных SQL Server и всех связанных с ней таблиц, представлений и процедур.Проблема в том, что DBAPI Python требует, чтобы cursor.execute() был включен в транзакцию, которая фиксируется только cursor.commit(), и вы не можете выполнить оператор drop или create database в транзакции пользователя.Есть какие-нибудь идеи о том, как это обойти?

Редактировать:

Похоже, что нет ничего аналогичного параметру автоматической фиксации ни для метода connect() adodbapi, ни для его метода cursor().Я был бы рад использовать pymssql вместо adodbapi, за исключением того, что он усекает типы данных char и varchar на 255 символов.

Я действительно пробовал это перед публикацией;вот обратная связь.

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
Это было полезно?

Решение

Объект подключения adodbapi conn автоматически запускает новую транзакцию после каждой фиксации, если база данных поддерживает транзакции.DB-API требует, чтобы функция автоматической фиксации была отключена по умолчанию, и это позволяет методу API снова включить ее, но я не вижу такого в adodbapi.

Возможно, вы смогли бы использовать conn.adoConn свойство обходить это, используя ADO api вместо DB-API, чтобы вывести вас из любой транзакции.Дайте мне знать, если это сработает:

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

Вот источник для метод adodbapi commit().

Другие советы

"Проблема в том, что DBAPI Python требует, чтобы cursor.execute() был включен в транзакцию, которая фиксируется только cursor.commit()"

"и вы не можете выполнить команду drop или create database в транзакции пользователя".

Я не уверен, что все это действительно верно для всех интерфейсов DBAPI.

Поскольку вы не показываете сообщения об ошибках, может оказаться, что это неверно для интерфейса ADODBAPI.Вы действительно пробовали это?Если да, то какое сообщение об ошибке вы получаете?

Соединение может не всегда создавайте "пользовательскую транзакцию".Вы часто можете открывать соединения с autocommit=True чтобы получить автоматическую фиксацию в стиле DDL.

Кроме того, вы можете рассмотреть возможность использования другого подключения для выполнения DDL.

http://pymssql.sourceforge.net/ например, показывает, что DDL выполняется следующим образом.

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

создайте фактическую базу данных вне транзакции.Я не знаком с python, но должен быть способ выполнить заданную пользователем строку в базе данных, используйте это с фактической командой create db.Затем используйте adodbapi для обработки всех таблиц и т.д. И зафиксируйте эту транзакцию.

У меня возникла такая же проблема при попытке запуска команд через adodbapi (напримерDBCC CHECKDB ...) и совет joeforker немного помог.Проблема, с которой я все еще сталкивался, заключалась в том, что adodbapi автоматически запускает транзакцию, поэтому не было возможности выполнить что-то вне транзакции.

В конце концов, я закончил тем, что отключил поведение фиксации adodbapi следующим образом:

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

Насколько я могу судить, это повторно включает стандартную функцию автоматической фиксации SQL Server, т.е.каждая инструкция SQL фиксируется автоматически.Недостатком является то, что у меня нет возможности снова включить транзакции (на данный момент), если я не хочу запускать что-либо внутри транзакции, поскольку Connection.commit() ничего не будет делать, когда supportsTransactions == False.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top