如果任何SQL命令失败,则启动回滚

时间:2013-05-19 13:48:19

标签: sql sql-server sql-server-2008 powershell

我正在考虑更新我为将Exchange邮件跟踪日志插入SQL而运行的旧PowerShell脚本。由于我将消息跟踪日志拉入制表符分隔的CSV文件然后导入它们的方式,我有一个很大的SQL语句,我想回滚并在出现错误或问题时抛出异常... < / p>

我按以下顺序执行此操作:

  1. 截断我之前在剧本中创建的临时表。
  2. 将CSV文件中的日志批量插入Temp Table。
  3. 将邮件跟踪行插入邮件跟踪表 来自临时表
  4. 将收件人信息插入Temp的Recipients表中 表
  5. 更新我的服务器表以反映我已成功的事实 及时前进并插入日志。
  6. 以下是来自PowerShell的功能,即使您不了解PowerShell,也应该很容易看到正在运行的内容:

    Function Import-TrackingLogs
    {
        $Command = New-Object System.Data.SQLClient.SQLCommand
        $Command.Connection = $Connection
        $Command.CommandTimeOut = 2000
        $Command.CommandText = "
        TRUNCATE TABLE $TempTable1;
    
        BULK INSERT $TempTable1
        FROM '$ExportTrackingFile'
        WITH
        (
            FIRSTROW = 2,
            FIELDTERMINATOR = '\t'
        );
    
        INSERT INTO E12_MessageTracking
        SELECT
        CASE LEN([TimeStamp]) WHEN 2 THEN NULL ELSE REPLACE([TimeStamp], '" + [char]34 + "', '') END AS [TimeStamp],
        CASE LEN([Sender]) WHEN 2 THEN NULL ELSE REPLACE([Sender], '" + [char]34 + "', '') END AS [Sender],
        CASE LEN([Recipients]) WHEN 2 THEN NULL ELSE REPLACE([Recipients], '" + [char]34 + "', '') END AS [Recipients],
        CASE LEN([MessageSubject]) WHEN 2 THEN NULL ELSE REPLACE([MessageSubject], '" + [char]34 + "', '') END AS [MessageSubject],
        CASE LEN([EventId]) WHEN 2 THEN NULL ELSE REPLACE([EventId], '" + [char]34 + "', '') END AS [EventId],
        CASE LEN([Source]) WHEN 2 THEN NULL ELSE REPLACE([Source], '" + [char]34 + "', '') END AS [Source],
        CASE LEN([MessageId]) WHEN 2 THEN NULL ELSE REPLACE([MessageId], '" + [char]34 + "', '') END AS [MessageId],
        CASE LEN([InternalMessageId]) WHEN 2 THEN NULL ELSE REPLACE([InternalMessageId], '" + [char]34 + "', '') END AS [InternalMessageId],
        CASE LEN([RecordGuid]) WHEN 2 THEN NULL ELSE REPLACE([RecordGuid], '" + [char]34 + "', '') END AS [RecordGuid],
        CASE LEN([ClientIp]) WHEN 2 THEN NULL ELSE REPLACE([ClientIp], '" + [char]34 + "', '') END AS [ClientIp],
        CASE LEN([ServerHostname]) WHEN 2 THEN NULL ELSE REPLACE([ServerHostname], '" + [char]34 + "', '') END AS [ServerHostname],
        CASE LEN([ConnectorId]) WHEN 2 THEN NULL ELSE REPLACE([ConnectorId], '" + [char]34 + "', '') END AS [ConnectorId],
        CASE LEN([RecipientStatus]) WHEN 2 THEN NULL ELSE REPLACE([RecipientStatus], '" + [char]34 + "', '') END AS [RecipientStatus],
        CASE LEN([RecipientCount]) WHEN 2 THEN NULL ELSE REPLACE([RecipientCount], '" + [char]34 + "', '') END AS [RecipientCount],
        CASE LEN([TotalBytes]) WHEN 2 THEN NULL ELSE REPLACE([TotalBytes], '" + [char]34 + "', '') END AS [TotalBytes],
        CASE LEN([FromServer]) WHEN 2 THEN NULL ELSE REPLACE([FromServer], '" + [char]34 + "', '') END AS [FromServer]
        FROM $TempTable1;
    
        INSERT INTO E12_MessageTracking_Recipients
        SELECT
        SUBSTRING (s.[TimeStamp], 2, LEN(s.[TimeStamp]) -2) AS [TimeStamp],
        CASE LEN(s.[MessageId]) WHEN 2 THEN NULL ELSE (SUBSTRING (s.[MessageId], 2, LEN(s.[MessageId]) -2)) END AS [MessageId],
        CASE LEN(s.[InternalMessageId]) WHEN 2 THEN NULL ELSE (SUBSTRING (s.[InternalMessageId], 2, LEN(s.[InternalMessageId]) -2)) END AS [InternalMessageId],
        CASE LEN(s.[RecordGuid]) WHEN 2 THEN NULL ELSE (SUBSTRING (s.[RecordGuid], 2, LEN(s.[RecordGuid]) -2)) END AS [RecordGuid],
        f.Value AS [Recipient]
        FROM #E12_MessageTracking AS s
        CROSS APPLY dbo.SplitStrings(SUBSTRING(s.[Recipients], 2, LEN(s.[Recipients]) -2), '|') AS f;
    
        UPDATE E12_MessageTracking_Servers
        SET LogUpdatedTime = '$EndTime';"
    
        $Command.ExecuteNonQuery() | Out-Null
    }
    

    我可以将每个单独的命令包装到一个Powershell tr​​y / catch块中,但是可能更好看看SQL是否可以为我处理这个问题。

    这是我之前在PowerShell中的回滚:

    $Command = New-Object System.Data.SQLClient.SQLCommand
    $Command.Connection = $Connection
    $Command.CommandTimeOut = 30
    $Command.CommandText = "
    DELETE FROM E12_MessageTracking WHERE TimeStamp >= '$StartTime';
    DELETE FROM E12_MessageTracking_Recipients WHERE TimeStamp >= '$StartTime';
    UPDATE E12_MessageTracking_Servers
    SET LogUpdatedTime = '$StartTime';"
    
    $Command.ExecuteNonQuery() | Out-Null
    

    我正在查看此页面SQL Server - transactions roll back on error?,但不确定如何将其包装到我的命令中,因为我不只是运行一件事,而是多个命令。

    谢谢!

1 个答案:

答案 0 :(得分:2)

考虑使用xact_abort

set xact_abort on
begin transaction
<your big sql statement here>
commit transaction