从 Python 创建 SQL Server 数据库

发布于 2024-07-19 06:13:19 字数 1778 浏览 6 评论 0原文

我使用 Python 和 pywin32 的 adodbapi 编写一个脚本来创建 SQL Server 数据库及其所有关联的表、视图和过程。 问题在于Python的DBAPI要求将cursor.execute()包装在仅由cursor.commit()提交的事务中,并且您无法在用户事务中执行删除或创建数据库语句。 关于如何解决这个问题有什么想法吗?

编辑:

似乎没有任何类似于adodbapi的connect()方法或其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

I'm using Python with pywin32's adodbapi to write a script to create a SQL Server database and all its associated tables, views, and procedures. The problem is that Python's DBAPI requires that cursor.execute() be wrapped in a transaction that is only committed by cursor.commit(), and you can't execute a drop or create database statement in a user transaction. Any ideas on how to get around that?

EDIT:

There does not seem to be anything analogous to an autocommit parameter to either the connect() method of adodbapi or its cursor() method. I'd be happy to use pymssql instead of adodbapi, except that it truncates char and varchar datatypes at 255 characters.

I did try this before posting; here's the traceback.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

对不⑦ 2024-07-26 06:13:19

“问题是Python的DBAPI要求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))')

"The problem is that Python's DBAPI requires that cursor.execute() be wrapped in a transaction that is only committed by cursor.commit()"

"and you can't execute a drop or create database statement in a user transaction."

I'm not sure all of this is actually true for all DBAPI interfaces.

Since you don't show the error messages, it may turn out that this is not true for ADODBAPI interface. Have you actually tried it? If so, what error message are you getting?

A connection may not always be creating a "user transaction". You can often open connections with autocommit=True to get DDL-style autocommit.

Also, you might want to consider using a different connection to do run DDL.

http://pymssql.sourceforge.net/ for example, shows DDL being executed like this.

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))')
清风挽心 2024-07-26 06:13:19

如果数据库支持事务,adodbapi 连接对象 conn 会在每次提交后自动启动一个新事务。 DB-API 要求默认情况下关闭自动提交,并且它允许 API 方法将其重新打开,但我在 adodbapi 中没有看到自动提交。

您也许可以使用 conn.adoConn 属性来解决此问题,使用 ADO api 而不是 DB-API 来退出任何事务。 让我知道这是否有效:

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

这是 adodbapi commit() 方法

The adodbapi connection object conn does automatically start a new transaction after every commit if the database supports transactions. DB-API requires autocommit to be turned off by default and it allows an API method to turn it back on, but I don't see one in adodbapi.

You might be able to use the conn.adoConn property to hack around this, using the ADO api instead of DB-API to take you out of any transaction. Let me know if this works:

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

Here's the source for the adodbapi commit() method.

羁〃客ぐ 2024-07-26 06:13:19

在事务之外创建实际的数据库。 我不熟悉 python,但必须有一种方法可以在数据库上执行用户给定的字符串,将其与实际的 create db 命令一起使用。 然后使用 adodbapi 执行所有表等操作并提交该事务。

create the actual db outside the transaction. I'm not familiar with python, but there has to be a way to execute a user given string on a database, use that with the actual create db command. Then use the adodbapi to do all the tables, etc and commit that transaction.

爱*していゐ 2024-07-26 06:13:19

我在尝试通过 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

I had this same issue while trying run commands over adodbapi (e.g. DBCC CHECKDB...) and joeforker's advice helped a bit. The problem I still had was that adodbapi automatically starts a transaction, so there was no way to execute something outside of a transaction.

In the end I ended up disabling adodbapi's commit behaviour like this:

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

As far as I can tell, this re-enables the standard SQL Server auto-commit functionality, i.e. each SQL statement is automatically committed. The downside is that there is no way for me to enabled transactions again (at the moment) if I wan't to run something within a transaction, since Connection.commit() will do nothing when supportsTransactions == False.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文