2013-05-19 36 views
0

我正在寻找更新旧的PowerShell脚本,我跑了插入Exchange邮件跟踪日志到SQL中。由于我将邮件跟踪日志拖入制表符分隔的CSV文件中,然后导入它们,我有一个很大的SQL语句,我想要回滚并在发生错误或问题时抛出异常...启动回滚,如果任何SQL命令失败

我按以下顺序这样做:

  1. 截断我已经在前面的脚本创建的临时表。
  2. 将CSV文件中的日志批量插入Temp表。
  3. 插入消息,从临时表
  4. 插入收件人信息到接收者表从Temp 表追踪行插入消息跟踪表 。
  5. 正在更新我的服务器表,以反映我已经成功地将 及时前移并插入日志。

下面是我的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的try/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?这个页面,但不确定我会如何换行到我的命令,我不只是运行的一两件事,但多个命令。

谢谢!

回答

2

考虑使用xact_abort

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

我补充说,似乎这样的伎俩感谢!我在语句中间插入了一个Divide by Zero,它并没有应用以前的更改,并且允许我在PowerShell中捕获Exception。 2013-05-19 16:50:53 - 遇到零分错误。在C:\ Path \ To \ Script \ ScriptName.ps1:87 char:26 + $ Command.ExecuteNonQuery <<<<()| Out-Null + CategoryInfo:NotSpecified:(:) [],SqlException + FullyQualifiedErrorId:DotNetMethodException – HungryHippos

+0

如果在出现错误时不应该在SQL语句结尾处检查错误,并且if语句发出'rollback',否则'提交'? – alroc

+0

@alroc:这就是'XACT_ABORT'所做的。如果有错误,它会回滚事务。 – Andomar