使用交易 - 最佳做法

时间:2018-04-16 04:27:50

标签: sql-server tsql stored-procedures transactions

假设我在SQL服务器中有一个程序:

create procedure BULKINSERT
AS
 INSERT INTO TABLEB (
 SELECT NAME, ID From TableA
)
GO   

TABLE A 读取数据并插入 TABLE B 的简单数据。如果我有100万条记录要插入表B,如果一条记录因任何原因失败,在这种情况下我应该使用 TRANSACTION 吗?

我应该回滚整个操作吗?

3 个答案:

答案 0 :(得分:2)

您可以将以下模板用于存储过程:

SET NOCOUNT, XACT_ABORT ON;

    BEGIN TRY

        BEGIN TRANSACTION;
        -- CODE BLOCK GOES HERE
        COMMIT TRANSACTION;

    END TRY
    BEGIN CATCH 

       IF @@TRANCOUNT > 0
       BEGIN
          ROLLBACK TRANSACTION
       END;

       -- GET ERRORS DETAILS OR THROW ERROR

    END CATCH;

SET NOCOUNT, XACT_ABORT OFF;

更多详情:

  • XACT_ABORT - 指定当Transact-SQL语句引发运行时错误时,SQL Server是否自动回滚当前事务;

  • 如果您需要有关错误的信息(ERROR_MESSAGE,ERROR_LINE,ERROR_NUMBER,ERROR_PROCEDURE,ERROR_SEVERITY,ERROR_STATE)

这是处理事务的一般技术。我会推荐Erland Sommarskog的以下文章:

  1. Error and Transaction Handling in SQL Server Part One – Jumpstart Error Handling
  2. Error and Transaction Handling in SQL Server Part Two – Commands and Mechanisms

答案 1 :(得分:1)

由于一个语句始终被视为原子语,并且此处只有1个语句,因此在TABLEB中插入了100万条记录,或者没有。但是,如果发生错误,您可能希望处理错误,在这种情况下,您应将INSERT放入TRY块并添加CATCH来处理错误时应采取的措施

要阅读有关该主题的更多信息,请查看以下来源以获得良好的起点:

答案 2 :(得分:1)

如上所述,单一陈述是一项交易。

对TABLEB的主键上的插入进行排序以减慢碎片。

要注意的一件事是多次插入相同的数据 如果你想阻止它然后离开加入pk。

declare @Ta table (id int identity primary key, name varchar(10));
declare @Tb table (id int          primary key, name varchar(10));
insert into @Ta values ('name'), ('name'), ('name'), ('name'), ('name'), ('name'), ('name'), ('nameL');

insert into @Tb (id, name)
select id, name from @Ta order by id;

select * from @Tb;

insert into @Tb (id, name)
select ta.id, ta.name 
from @Ta ta 
left join @Tb tb 
  on tb.id = ta.id 
where tb.id is null 
order by ta.id;

select * from @Tb;

如果要更新现有搜索合并命令的数据。