2013-02-21 5 views
43

Nella procedura memorizzata, sono presenti tre istruzioni di inserimento.Come eseguire il rollback o il commit di una transazione in SQL Server

Su duplicati inserimento valore della chiave prime due query generano l'errore

Violazione del vincolo PRIMARY KEY

e la terza query viene eseguita come al solito.

Ora voglio che se qualsiasi query genera qualche eccezione, tutto dovrebbe essere ripristinato.

Se non vi è alcuna eccezione generata da alcuna query, è necessario eseguire il commit.

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

Benvenuti in StackOverflow: se inserisci codice, XML o campioni di dati, ** per favore ** evidenzia queste righe nell'editor di testo e fai clic sul pulsante "esempi di codice" ('{}') sulla barra degli strumenti dell'editor per il formato e la sintassi lo evidenziano! –

+0

@marc_s grazie marc. Ho aggiunto il mio StoreProcedure. Per favore controlla. –

+0

È una ** stored procedure ** - una ** procedura ** che è ** memorizzata ** all'interno di SQL Server - non ha nulla a che fare con un "negozio" .... –

risposta

132

La buona notizia è una transazione in SQL Server può estendersi su più lotti (ogni exec viene trattato come un lotto separato.)

È possibile avvolgere le EXEC dichiarazioni in un BEGIN TRANSACTION e COMMIT ma dovrete è necessario fare un ulteriore passo avanti e il rollback se si verificano errori.

Idealmente si vorrebbe qualcosa di simile:

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

    IF @@TRANCOUNT > 0 
     ROLLBACK 
END CATCH 

Il BEGIN TRANSACTION e COMMIT credo si ha già familiarità con. I blocchi BEGIN TRY e BEGIN CATCH sono fondamentalmente lì per catturare e gestire eventuali errori che si verificano. Se una qualsiasi delle tue affermazioni EXEC genera un errore, l'esecuzione del codice passerà al blocco CATCH.

Il codice di edificio SQL esistente deve essere al di fuori della transazione (sopra) poiché si desidera mantenere sempre le transazioni il più brevi possibile.

+1

quando ho eseguito la dichiarazione. Funziona bene. ma in storeProcedure quando funziona la prima volta. Alla seconda esecuzione di storeP genera l'eccezione: - "Conteggio transazioni dopo EXECUTE indica un numero non corrispondente di istruzioni BEGIN e COMMIT. Conteggio precedente = 0, conteggio corrente = 1". –

+2

Spiacente, che avrebbe dovuto essere "IF @@ TRANCOUNT> 0", aggiornerò la mia risposta. –

+0

Grazie. ora sta funzionando bene. –