问题描述
我需要使用Python将CSV文件插入到sql Server上的表中(BULK INSERT
已关闭)。我不是使用sqlAlchemy
,而是编写自己的函数(上帝可以原谅我)。我正在将sql代码列表创建为字符串
sql_code_list = ["insert into table_name values (1,'aa'),(2,'ab'),(3,'ac')...(100,'az')","insert into table_name values (101,'ba'),(102,'bb'),(103,'bc')...(200,'bz')"]
,我计划使用pyodbc
软件包一个接一个地在数据库中运行它们。为了确保数据完整性,我想使用BEGIN TRANS ... ROLLBACK / COMMIT TRANS ...
语法。所以我想发送命令
DECLARE @TransactionName varchar(20) = 'TransInsert'
BEGIN TRANS @TransactionName
然后发送我所有的```INSERT``语句,并发送成功
DECLARE @TransactionName varchar(20) = 'TransInsert'
COMMIT TRANS @TransactionName
或失败
DECLARE @TransactionName varchar(20) = 'TransInsert'
ROLLBACK TRANS @TransactionName
将有许多INSERT语句,比方说10,000条语句,每条语句插入100行,我计划从同一connection.cursor
对象中分批发送它们。这整体看起来像是正确的程序吗?从Python应用程序发送这些命令可能会遇到什么问题?
解决方法
这里不需要命名交易。
您可以提交多个这样的事务性批处理,以有条件地回滚并引发错误:
SET XACT_ABORT,NO_COUNT ON;
BEGIN TRY
BEGIN TRAN;
<insert-statements-here>;
COMMIT;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK;
THROW;
END CATCH;
最大SQL Server批处理大小为64K *,默认网络数据包大小为4K,因此默认情况下,每个批处理最大为256MB。 1万次插入可能会在该限制内,因此您可以尝试将所有批量发送一次,然后仅在需要时将其分成多个较小的批次。
另一种插入多行的方法是使用来自表值参数源的INSERT...SELECT
。有关传递TVP值的示例,请参见this answer。我希望使用该技术会带来更好的性能,因为它避免了解析大批数据并且SQL Server在内部将TVP数据批量插入tempdb。