Создание базы данных SQL Server из Python

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

РЕДАКТИРОВАТЬ:

Кажется, нет ничего похожего на параметр autocommit ни для метода 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

4 ответа

Решение

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

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

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

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

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

"и вы не можете выполнить удаление или создать оператор базы данных в пользовательской транзакции".

Я не уверен, что все это на самом деле верно для всех интерфейсов 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,

Другие вопросы по тегам