在SQLServer表中,我想将colB中的值更新为transformColumn(colA),其中transformColumn是一个我不想转换为SQL的python函数。 我尝试了下面的代码,但显然我不能以这种方式同时查询和更新:
Error: ('HY000', '[HY000] [Microsoft][ODBC SQL Server Driver]Connection is busy with results for another hstmt (0) (SQLExecDirectW)')
我如何实现目标?
import pyodbc
def transformColumn(colValue):
#complicated transformation that I don't want to do in SQL here
cs = 'DRIVER={SQL Server};Server=mySvr;Database=myDB;Trusted_Connection=Yes;'
cn = pyodbc.connect(cs, autocommit=True)
sqlSelect = """
SELECT id, colA
FROM myTable
"""
sqlUpdate = """
UPDATE myTable
SET colB=? WHERE id=?
"""
csrSelect = cn.cursor()
rows = csrSelect.execute(sqlSelect)
csrUpdate = cn.cursor()
row = csrSelect.fetchone()
while row is not None:
colB = transformColumn(row.colA)
csrUpdate.execute(sqlUpdate, colB, row.id)
row = csrSelect.fetchone()
csrSelect.close()
csrUpdate.close()
cn.close()
答案 0 :(得分:2)
如果[colA]上有索引,则以下方法可能是可行的替代方法:
crsr = cnxn.cursor()
crsr.execute("SELECT DISTINCT colA FROM myTable")
aList = [item[0] for item in crsr.fetchall()]
for aValue in aList:
crsr.execute("UPDATE myTable SET colB=? WHERE colA=?", (transformColumn(aValue), aValue))
crsr.close()
cnxn.commit()
如果[colA]中有重复的值,那将特别有用,因为只计算变换并为每个唯一的[colA]值应用一次
答案 1 :(得分:1)
myTable
中的数据是否总是足够小以适应执行此代码的计算机上的内存(例如,总是一个小的查找表,还是会随着时间的推移而继续增长)?
是强>
使用Cursor.fetchall()将myTable
行读入列表,释放光标以用于UPDATE
# starting line 19 in the code sample
csr = cn.cursor()
# this creates a list of pyodbc.Row objects,
# freeing the cursor for update statement execution
rows = csr.execute(sqlSelect).fetchall()
for row in rows:
colB = transformColumn(row.colA)
csr.execute(sqlUpdate, colB, row.id)
cn.commit()
否强>
如您所述,为select和update语句使用单独的连接。对于大量数据,这将比上述方法表现更好。它确实需要管理两个连接和游标对象,因为在迭代选择游标时将执行更新。
# starting at line 7 in the code sample
cnSelect = pyodbc.connect(cs, autocommit=True)
cnUpdate = pyodbc.connect(cs, autocommit=True)
sqlSelect = """
SELECT id, colA
FROM myTable
"""
sqlUpdate = """
UPDATE myTable
SET colB=? WHERE id=?
"""
csrSelect = cnSelect.cursor()
csrUpdate = cnUpdate.cursor()
rows = csrSelect.execute(sqlSelect)
for row in rows:
colB = transformColumn(row.colA)
csrUpdate.execute(sqlUpdate, colB, row.id)
cnUpdate.commit()
答案 2 :(得分:-1)
对此的简单解决方案是使用游标,
cnxn = pyodbc.connect("YOUR SERVER DETAILS, CREDENTIALS")
cursor = cnxn.cursor()
query1 = "SELECT * FROM myTable1"
cursor.execute(query1)
query2 = "SELECT * FROM myTable2"
cursor.execute(query2)
这样你在同一个程序中就不需要多个连接了,