许多(1000+)INSERTS的T-SQL事务被断开连接

时间:2013-05-01 16:07:39

标签: sql-server tsql transactions sql-insert

您可以在事务中放置INSERT语句的数量是否有限制? 我收到传输错误,并且在运行语句的过程中连接断开连接。

我应该只填充临时表,然后运行单个INSERT语句吗?

错误消息在事务中1000+插入的中间...

Msg 233, Level 20, State 0, Line 0
A transport-level error has occurred when receiving results from the server. 
(provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.)

我在本地Windows 8计算机上的数据库中运行SQL Server 2008 R2 10.50.4000.0中的脚本(Toshiba Satellite S955,x64 8GB RAM,Intel(R)Core(TM)i5-3317U CPU @ 1.70GHz 1.70 GHz )

declare @currentDatabase nvarchar(255);
select @currentDatabase = DB_NAME();

if CHARINDEX('canada', @currentDatabase) = 0
begin
    print 'Please run this script on the Canada server'
    return
end

begin try
begin transaction
SET IDENTITY_INSERT company_name ON
insert into company_name (company_name_id, company_name, display_index, approved_by_administrator, requestor_id, modify_timestamp, active, create_timestamp) values (10000601010001, '6 Day Dental', 5868, 1, NULL, '2013-04-08 00:00:00.000', 1, '2013-04-08 00:00:00.000');
insert into company_name (company_name_id, company_name, display_index, approved_by_administrator, requestor_id, modify_timestamp, active, create_timestamp) values (10000601010002, '7-Eleven', 5869, 1, NULL, '2013-04-08 00:00:00.000', 1, '2013-04-08 00:00:00.000');
insert into company_name (company_name_id, company_name, display_index, approved_by_administrator, requestor_id, modify_timestamp, active, create_timestamp) values (10000601010003, 'AC Properties', 5870, 1, NULL, '2013-04-08 00:00:00.000', 1, '2013-04-08 00:00:00.000');
-- 1287 more INSERT statements...
SET IDENTITY_INSERT company_name OFF

commit
end try
begin catch
    rollback
    declare @Msg nvarchar(max)
    select @Msg=Error_Message();
    raiserror('Error Occured: %s', 20, 101,@Msg) with log
end catch

4 个答案:

答案 0 :(得分:2)

问题

我相信你的问题在于以下几行:

raiserror('Error Occured: %s', 20, 101,@Msg) with log

首先,让我们看一下RAISERROR的签名:

  

RAISERROR({msg_id | msg_str | @local_variable}
      {,严重性,状态}
      [,论证[,... n]])
      [WITH option [,... n]]

正如强调的那样,我要关注的是严重性参数。在同一MSDN page内,您将找到以下内容(关于严重性参数):

  

[severity]用户定义的严重性级别是否与此消息相关联

此外:

  

任何用户都可以指定从0到18的严重级别。从19到25的严重级别只能由sysadmin固定服务器角色的成员或具有ALTER TRACE权限的用户指定。对于从19到25的严重性级别,需要WITH LOG选项。

到目前为止,这么好。在您的代码段中,我们可以看到通过RAISERROR生成了严重性级别 20 的错误消息。因此,使用了WITH LOG选项。

然而,MSDN page也注明:

  

从20到25的严重程度被认为是致命的。如果遇到致命严重性级别,客户端连接在收到消息后终止,并在错误和应用程序日志中记录错误。

因此,实际上,您对RAISERROR的呼叫正在终止您的连接。

解决方案

我假设您对CATCH块的意图是“重新抛出”导致CATCH块运行的原始错误。如果是这样,请查看以下内容(摘自Is there an equivalent in T-SQL to C#'s "throw;" to re-throw exceptions?):

...
BEGIN CATCH
    DECLARE @ErrorMessage NVARCHAR(4000);
    DECLARE @ErrorSeverity INT;
    DECLARE @ErrorState INT;

    SELECT @ErrorMessage = ERROR_MESSAGE(),
           @ErrorSeverity = ERROR_SEVERITY(),
           @ErrorState = ERROR_STATE();

    -- Use RAISERROR inside the CATCH block to return 
    -- error information about the original error that 
    -- caused execution to jump to the CATCH block.
    RAISERROR (@ErrorMessage, -- Message text.
               @ErrorSeverity, -- Severity.
               @ErrorState -- State.
               );
END CATCH;

这使用ERROR_MESSAGE()ERROR_SEVERITY()ERROR_STATE()来收集有关导致CATCH块运行的错误的信息。然后,它使用RAISERROR生成包含所述信息的新错误消息。

答案 1 :(得分:0)

您确实知道每次插入可以插入多组值。

values (), (), ()  

有一个最佳的。值的总数应小于1024 看起来你有8个值,所以每个插入128()。

答案 2 :(得分:0)

您还可以尝试更基于集合的替代语法。

INSERT INTO dbo.Employee ( LastName, FirstName ) 
          Select 'Smith', 'John'
UNION ALL Select 'Jones', 'Mary'
UNION ALL Select 'Packer', 'Penny'
UNION ALL Select 'Stokes', 'Daryl'

答案 3 :(得分:0)

UNION看起来像一个语句而不是1290,因此更好

(带有硬编码内容的1290个单独的陈述真让我害怕)