pymssql 多插入单次提交

0 投票
1 回答
1477 浏览
提问于 2025-04-18 11:55

我正在尝试在数据库中进行多次插入操作,要求只有在所有插入成功的情况下,才能提交这些操作。如果有任何一个插入失败,就要撤销所有的操作。在TSQL中,我可以很简单地通过把整个代码块包裹起来来实现这个功能:

BEGIN TRANSACTION
BEGIN TRY
    --INSERTIONS GO HERE
    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION;
    SELECT Error = 1
END CATCH

现在,如果我想在Python中使用PYMSSQL来实现同样的功能,我尝试了以下方法:

sql=""" SOME SQL CODE HERE """

try:
    cursor = DB.execute(sql)
except:
    DB.rollback()
    print('Fail')
    return False

sql=""" SOME DIFFERENT SQL CODE HERE """

try:
    cursor = DB.execute(sql)
except:
    DB.rollback()
    print('Fail')
    return False

DB.commit()
print('Success')
return True

结果是没有任何事务被提交,数据库中没有看到任何变化。而且,如果我在进行一次插入后尝试提交,虽然插入成功了,但由于一些复杂的父子关系,这个任务要求要么所有插入都成功,要么一个都不插入。

我还应该提到,我使用单例模式保持了一个持久的数据库连接,这样可以覆盖常规的连接方法,但只允许打开一个连接:

def __init__(self, connid='one'):
     self.ensure_conn(connid)

 def ensure_conn(self, connid='one'):
     conn = getattr(self.connection_stack, connid, None)
     if conn is None:
         conn = pymssql.connect(
             self.server, self.user, self.password, self.database)
         self.connection_stack[connid] = conn

 def conn(self, connid='one'):
     self.ensure_conn(connid)
     if connid in self.connection_stack:
         return self.connection_stack[connid]
     else:
         return None

我尝试在网上寻找相关的例子,但这个问题似乎有点独特,所以任何建议或意见都非常感谢。

1 个回答

0

我找到的解决办法是使用TSQL中的存储过程,并利用pymssql的远程过程调用功能。这需要在SQL账户层面有EXEC权限,但为了安全考虑,可以限制只对特定的存储过程开放权限。

这样做可以让你在不同的表上进行多条插入时,享受到事务处理的好处。

cursor.callproc(name, args)

撰写回答