2009-05-12 4 views
3

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

EDIT:

Там, кажется, не будет ничего аналогично параметру автоматической фиксации либо метода подключения() из adodbapi или способа его курсора(). Я был бы рад использовать 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 

ответ

1

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

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

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

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

+1

Это близко. Что в итоге получилось: conn.adoConn.Execute ("создать базу данных dummydatabase") Спасибо! Возможно, я никогда не подумал об этом. – JasonFruit

0

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

+0

Да, это хорошая переформулировка вопроса. Вы знаете, как это сделать? Adodbapi в значительной степени недокументирован, но я прорыл его модульные тесты, и нет теста, который отвечает за выполнение команды SQL вне транзакции. – JasonFruit

+0

попробуйте что-то другое, кроме adodbapi, чтобы выполнить команду create –

1

«Проблема заключается в том, что DBAPI Python требует, чтобы cursor.execute() быть завернуты в сделке, только совершенное cursor.commit()»

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

Я не уверен, что все это действительно верно для всех интерфейсов 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))') 
+0

Вы правы - это не относится к * всем * интерфейсам DBAPI, но это предпочтительный подход, когда провайдер это разрешает. Я обновил свой вопрос с дополнительной информацией, относящейся к вашему ответу. Спасибо за идеи! – JasonFruit

0

У меня была эта же проблема при попытке выполнить команды над 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.

Смежные вопросы