2013-05-19 4 views
0

Exchange 메시지 추적 로그를 SQL에 삽입하기 위해 실행 한 이전 PowerShell 스크립트를 업데이트하려고합니다. 내가 탭으로 구분 된 CSV 파일로 메시지 추적 로그를 가져 와서 가져 오는 방법으로 인해 롤백하고 오류 또는 문제가 발생했을 때 예외를 throw하는 꽤 큰 SQL 문이 있습니다.SQL 명령이 실패 할 경우 롤백 시작

나는 다음과 같은 순서로이 일을하고있다 :

  1. 내가 이전 스크립트에서 만들어진 거라고 임시 테이블을 자르는.
  2. CSV 파일의 로그를 임시 테이블에 대량 삽입합니다.
  3. 임시 표에서받는 사람 테이블에받는 사람의 정보를 삽입 임시 테이블
  4. 에서 메시지 추적 테이블 에 행을 추적 메시지를 삽입.
  5. 내 서버 테이블을 업데이트하여 성공적으로 을 단계적으로 수행하고 로그를 삽입했음을 반영합니다.

    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 
    } 
    

    나는 파워 쉘의 try/catch 블록에 각각의 명령을 포장 수 : 아래

PowerShell을에서 내 기능, 당신은 PowerShell을 모르더라도 실행하는 것을 쉽게 볼 수 있어야 ,하지만 SQL이 나를 위해 이것을 처리 할 수 ​​있는지보기가 더 쉬울 수도 있습니다.

은 PowerShell의 내 이전 롤백했다 :이 페이지 SQL Server - transactions roll back on error?보고,하지만 난 한 가지를 운영하지 않는 나는 내 명령에 그 포장 얼마나 확실하지만, 여러 명령했다

$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 

.

감사합니다.

답변

2

xact_abort 사용을 고려 :

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

는 그 추가 트릭 감사 할 것 같습니다! 성명 중간에 의도적으로 Zero by Divide를 삽입했는데 이전 변경 사항이 적용되지 않아 PowerShell의 예외도 catch 할 수있었습니다. 2013-05-19 16:50:53 - 0으로 나누기 오류가 발생했습니다. C : \ Path \ To \ Script \ ScriptName.ps1에서 87 char : 26 + $ Command.ExecuteNonQuery <<<<() | Out-Null + CategoryInfo : NotSpecified : (:) [], SqlException + FullyQualifiedErrorId : DotNetMethodException – HungryHippos

+0

오류가있는 경우 '롤백'을 실행하는 SQL 문 및 if 문 끝 부분에 오류 검사가 없어야합니다. 그렇지 않으면'commit'? – alroc

+0

@alroc : 그것이 바로'XACT_ABORT'입니다. 오류가 있으면 트랜잭션을 롤백합니다. – Andomar