问题描述
我现在通过pyodbc同时处理2个表。 在完成处理之前,我想在2个表上放置锁,以便在我完成之前没有人可以更改2个表。 我怎样才能做到这一点?
我尝试了以下操作,但失败并显示错误。
import pyodbc
conn = pyodbc.connect("conn_str")
conn.execute("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;")
conn.execute("begin transaction trans;")
cur1 = conn.execute("select * from tbl1;")
cur2 = conn.execute("select * from tbl2;")
... some processing at cur1 and cur2 at python ...
conn.execute("commit transaction trans;")
但是,执行“ cur2 = conn.execute(“从tbl2; *中选择*)”时会出现以下错误
[Microsoft][ODBC SQL Server Driver]Connection is busy with results for another hstmt (0) (SQLExecDirectW)
我的代码有什么问题吗? 非常感谢您的帮助。
1楼
最初,SQL Server ODBC每个连接仅限于一个活动的hstmt
(相当于pyodbc.cursor
的ODBC)。
稍后,Microsoft将MARS(多个活动结果集)功能添加到SQL Server ODBC,但是默认情况下该功能为“关闭”。
所以这段代码
import pyodbc
import sys
print(f"Python version {sys.version}") # Python version 3.6.4 ...
print(f"pyodbc version {pyodbc.version}") # pyodbc version 4.0.24
conn_str = (
r'DRIVER=ODBC Driver 17 for SQL Server;'
r'SERVER=.\SQLEXPRESS;'
r'DATABASE=myDb;'
r'Trusted_Connection=yes;'
)
cnxn = pyodbc.connect(conn_str, autocommit=True)
cnxn.set_attr(pyodbc.SQL_ATTR_TXN_ISOLATION, pyodbc.SQL_TXN_SERIALIZABLE)
cnxn.autocommit = False # enable transactions
cur1 = cnxn.execute("SELECT 1 AS x UNION ALL SELECT 2 AS x")
cur2 = cnxn.execute("SELECT 'foo' AS y UNION ALL SELECT 'bar' AS y")
print(cur1.fetchone())
print(cur2.fetchone())
print(cur1.fetchone())
print(cur2.fetchone())
失败于
Traceback (most recent call last):
File "C:/Users/Gord/PycharmProjects/py3pyodbc_demo/main.py", line 18, in <module>
cur2 = cnxn.execute("SELECT 'foo' AS y UNION ALL SELECT 'bar' AS y")
pyodbc.Error: ('HY000', '[HY000] [Microsoft][ODBC Driver 17 for SQL Server]Connection is busy with results for another command (0) (SQLExecDirectW)')
但是,如果我们将MARS_Connection=yes
添加到连接字符串
conn_str = (
r'DRIVER=ODBC Driver 17 for SQL Server;'
r'SERVER=.\SQLEXPRESS;'
r'DATABASE=myDb;'
r'Trusted_Connection=yes;'
r'MARS_Connection=yes;'
)
然后代码工作。
不幸的是,在您的情况下,您使用的是古老的DRIVER=SQL Server
,它太旧了,无法支持MARS_Connection=yes
因此您的选择
- 使用较新版本的SQL Server ODBC驱动程序,或
- 打开两个单独的连接,每个游标一个。