2013-02-21 10 views
43

In meiner gespeicherten Prozedur habe ich drei Einfügeanweisungen.Wie Rollback oder Commit einer Transaktion in SQL Server

Auf doppelten Schlüsselwert Einfügungs ersten zwei Abfragen erzeugen, um den Fehler

Verletzung der PRIMARY KEY Constraint

und dritten Abfrage wie üblich ausgeführt.

Jetzt möchte ich, dass, wenn irgendeine Abfrage irgendeine Ausnahme erzeugt, alles zurückgerollt werden sollte.

Wenn von keiner Abfrage eine Ausnahme generiert wird, sollte sie festgeschrieben werden.

declare @QuantitySelected as char 
    set @QuantitySelected = 2 

    declare @sqlHeader as varchar(1000) 
    declare @sqlTotals as varchar(1000) 
    declare @sqlLine as varchar(1000) 

    select @sqlHeader = 'Insert into tblKP_EstimateHeader ' 
    select @sqlHeader = @sqlHeader + '(CompanyID,CompanyName,ProjectName,EstimateID,EstimateHeader,QuoteDate,ValidUntil,RFQNum,Revision,Contact,Status,NumConfigurations) ' 
    select @sqlHeader = @sqlHeader + ' select CompanyID,CompanyName,ProjectName,EstimateID,EstimateHeader,QuoteDate,ValidUntil,RFQNum,Revision,Contact,Status,NumConfigurations ' 
    select @sqlHeader = @sqlHeader + 'from V_EW_Estimate_Header where EstimateID = 2203' 



    select @sqlTotals = 'Insert into tblKP_Estimate_Configuration_Totals ' 
    select @sqlTotals = @sqlTotals + '(ConfigRecId,RecId,SellQty,ConfigNum,ConfigDesc,SortOrder,OptionsInMainPrice,MarkupPctQty,' 
    select @sqlTotals = @sqlTotals + ' SellPriceQty,RubberStamp,OptPriceQty,StatusRecid,LastUpdate_Date,LastUpdate_User,TotalCost,QuantityBracketSelected)' 
    select @sqlTotals = @sqlTotals + ' select ConfigRecId,RecId,SellQty' + @QuantitySelected + ',ConfigNum,ConfigDesc,SortOrder,OptionsInMainPrice' 
    select @sqlTotals = @sqlTotals + ' ,MarkupPctQty' + @QuantitySelected + ',SellPriceQty' + @QuantitySelected + ',RubberStamp,OptPriceQty' + @QuantitySelected + ',StatusRecid,LastUpdate_Date,LastUpdate_User,TotalCost' + @QuantitySelected + ',' + @QuantitySelected 
    select @sqlTotals = @sqlTotals + ' from v_EW_Estimate_Configuration_Totals where ConfigRecId = -3' 


    select @sqlLine = 'Insert into tblKP_Estimate_Configuration_Lines' 
    select @sqlLine = @sqlLine + '(MstrRfqRecId,RfqRecId,RfqLineRecId,CompanyId,VendorQuoteNum,LineGrp,LineNum,StatusRecId,' 
    select @sqlLine = @sqlLine + ' LineDesc,LineSize,LineMatl,LineDeco,LineFinish,CopyFromRecId,PerPieceCost,IsOptional,' 
    select @sqlLine = @sqlLine + ' CopyToNewRev,RecId,UnitPrice,LineQty,LinePrice,CustOrVend,SellQty1,RfqNum,ConfigLineIsOptional,ConfigLinePerPieceCost,ConfigLineRecid,SellPrice,SaleQty)' 
    select @sqlLine = @sqlLine + ' select distinct MstrRfqRecId,RfqRecId,RfqLineRecId,CompanyId,VendorQuoteNum,LineGrp,LineNum,' 
    select @sqlLine = @sqlLine + ' StatusRecId,LineDesc,LineSize,LineMatl,LineDeco,LineFinish,CopyFromRecId,PerPieceCost,IsOptional,' 
    select @sqlLine = @sqlLine + ' CopyToNewRev,RecId,UnitPrice' + @QuantitySelected + ',LineQty' + @QuantitySelected + ', isnull(LinePrice' + @QuantitySelected + ', 0.0000),CustOrVend,SellQty' + @QuantitySelected + ',RfqNum,ConfigLineIsOptional,ConfigLinePerPieceCost,ConfigLineRecid,SellPrice' + @QuantitySelected + ',SaleQty' + @QuantitySelected 
    select @sqlLine = @sqlLine + ' from v_EW_EstimateLine where rfqlinerecid in (select RfqLineRecID from kp_tblVendorRfqConfigLine where ConfigRecID = -3) ' 

    exec(@sqlHeader) 
    exec(@sqlTotals) 
    exec(@sqlLine) 
+0

Willkommen zu StackOverflow: Wenn Sie Code, XML oder Datenbeispiele postulieren, ** bitte ** markieren Sie diese Zeilen im Texteditor und klicken Sie auf den "Code Samples" Button ('{}') auf der Editor-Symbolleiste Format und Syntax unterstreichen es! –

+0

@marc_s danke marc. Ich habe mein StoreProcedure hinzugefügt. Bitte schau es dir an. –

+0

Es ist eine ** gespeicherte Prozedur ** - eine ** Prozedur **, die ** in SQL Server ** gespeichert ist - es hat nichts mit einem "Geschäft" zu tun .... –

Antwort

132

Die gute Nachricht ist in SQL Server eine Transaktion mehrere Chargen umfassen kann (jeweils exec als separate Charge behandelt wird.)

Sie können Ihre EXEC Anweisungen in einer BEGIN TRANSACTION und COMMIT wickeln aber Sie werden müssen einen Schritt weiter gehen und ein Rollback durchführen, wenn Fehler auftreten.

Im Idealfall würde man so etwas wie dies wollen:

BEGIN TRY 
    BEGIN TRANSACTION 
     exec(@sqlHeader) 
     exec(@sqlTotals) 
     exec(@sqlLine) 
    COMMIT 
END TRY 
BEGIN CATCH 

    IF @@TRANCOUNT > 0 
     ROLLBACK 
END CATCH 

Die BEGIN TRANSACTION und COMMIT Ich glaube, mit denen Sie bereits vertraut sind. Die BEGIN TRY und BEGIN CATCH Blöcke sind grundsätzlich da, um alle auftretenden Fehler zu erfassen und zu behandeln. Wenn eine Ihrer EXEC-Anweisungen einen Fehler auslöst, springt die Codeausführung zum Block CATCH.

Ihr bestehender SQL-Building-Code sollte außerhalb der Transaktion (oben) liegen, da Sie Ihre Transaktionen immer so kurz wie möglich halten möchten.

+1

, als ich die Anweisung ausführte. Es funktioniert gut. aber im storeProcedure, wenn es das erste Mal funktioniert. Bei der zweiten Ausführung von storeP erzeugt es die Ausnahme: - "Transaktionsanzahl nach EXECUTE zeigt eine nicht übereinstimmende Anzahl von BEGIN- und COMMIT-Anweisungen an. Vorherige Zählung = 0, aktuelle Zählung = 1." –

+2

Entschuldigung, das hätte 'IF @@ TRANCOUNT> 0' sein sollen, ich werde meine Antwort aktualisieren. –

+0

Danke. jetzt funktioniert es gut. –

Verwandte Themen