有一個大規模升級到SQL Server 2005中處理錯誤這些文章是相當廣泛:Error Handling in SQL 2005 and Later by Erland Sommarskog和Error Handling in SQL 2000 – a Background by Erland Sommarskog
最好的辦法是這樣的:
創建存儲過程,如:
CREATE PROCEDURE YourProcedure
AS
BEGIN TRY
BEGIN TRANSACTION --SqlTransaction
DECLARE @ReturnValue int
SET @ReturnValue=NULL
IF (DAY(GETDATE())=1 --logical error
BEGIN
SET @ReturnValue=5
RAISERROR('Error, first day of the month!',16,1) --send control to the BEGIN CATCH block
END
SELECT 1/0 --actual hard error
COMMIT TRANSACTION --SqlTransaction
RETURN 0
END TRY
BEGIN CATCH
IF XACT_STATE()!=0
BEGIN
ROLLBACK TRANSACTION --only rollback if a transaction is in progress
END
--will echo back the complete original error message to the caller
--comment out if not needed
DECLARE @ErrorMessage nvarchar(400), @ErrorNumber int, @ErrorSeverity int, @ErrorState int, @ErrorLine int
SELECT @ErrorMessage = N'Error %d, Line %d, Message: '+ERROR_MESSAGE(),@ErrorNumber = ERROR_NUMBER(),@ErrorSeverity = ERROR_SEVERITY(),@ErrorState = ERROR_STATE(),@ErrorLine = ERROR_LINE()
RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorNumber,@ErrorLine)
RETURN ISNULL(@ReturnValue,1)
END CATCH
GO
但是這隻適用於SQL Server 2005以上。如果不使用SQL Server 2005中的TRY-CATCH塊,您將很難刪除SQL Server發回的所有消息。該extra messages
你指的是通過回滾的是如何使用@@ TRANCOUNT處理的性質造成的:
從http://www.sommarskog.se/error-handling-I.html#trancount
@@ TRANCOUNT是 反映嵌套 交易水平的全局變量。每個由1 BEGIN TRANSACTION 增加@@ TRANCOUNT,並且每個 COMMIT TRANSACTION減小 @@ TRANCOUNT由1沒有實際上是 致力於直到@@ TRANCOUNT達到0 回滾事務回滾 一切到最外面的BEGIN TRANSACTION(除非您已使用 頗具異國情調的SAVE TRANSACTION),並且 強制@@ trancount爲0,關注 以前的值。
當你退出的存儲過程,如果 @@ TRANCOUNT不具有相同的 價值,因爲它有當程序 動工執行,SQL Server將 錯誤266是不是引發此錯誤, 不過,如果該過程從觸發器直接調用 ,或直接調用 。也不是,如果你 與組隱 交易上運行
如果您不想獲得有關交易的警告數不匹配,你只需要在任何一次打開一個交易它提出。你可以通過創建你所有的程序來做到這一點:
CREATE PROC YourProcedure
AS
DECLARE @SelfTransaction char(1)
SET @SelfTransaction='N'
IF @@trancount=0
BEGIN
SET @SelfTransaction='Y'
BEGIN TRANSACTION --SqlTransaction
END
SELECT 1/0
IF @@ERROR<> 0
BEGIN
IF @SelfTransaction='Y'
BEGIN
ROLLBACK TRANSACTION --SqlTransaction
END
RETURN -1
END
ELSE
BEGIN
IF @SelfTransaction='Y'
BEGIN
COMMIT TRANSACTION --SqlTransaction
END
RETURN 0
END
GO
通過這樣做,如果你還沒有在事務中,你只能發出事務命令。如果你用這種方式編寫所有的程序,只有發佈BEGIN TRANSACTION的程序或C#代碼實際上會發出COMMIT/ROLLBACK,並且事務計數總是匹配的(你不會得到錯誤)。
在C#
從TransactionScope Class Documentation:
static public int CreateTransactionScope(
string connectString1, string connectString2,
string commandText1, string commandText2)
{
// Initialize the return value to zero and create a StringWriter to display results.
int returnValue = 0;
System.IO.StringWriter writer = new System.IO.StringWriter();
try
{
// Create the TransactionScope to execute the commands, guaranteeing
// that both commands can commit or roll back as a single unit of work.
using (TransactionScope scope = new TransactionScope())
{
using (SqlConnection connection1 = new SqlConnection(connectString1))
{
// Opening the connection automatically enlists it in the
// TransactionScope as a lightweight transaction.
connection1.Open();
// Create the SqlCommand object and execute the first command.
SqlCommand command1 = new SqlCommand(commandText1, connection1);
returnValue = command1.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command1: {0}", returnValue);
// If you get here, this means that command1 succeeded. By nesting
// the using block for connection2 inside that of connection1, you
// conserve server and network resources as connection2 is opened
// only when there is a chance that the transaction can commit.
using (SqlConnection connection2 = new SqlConnection(connectString2))
{
// The transaction is escalated to a full distributed
// transaction when connection2 is opened.
connection2.Open();
// Execute the second command in the second database.
returnValue = 0;
SqlCommand command2 = new SqlCommand(commandText2, connection2);
returnValue = command2.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
}
}
// The Complete method commits the transaction. If an exception has been thrown,
// Complete is not called and the transaction is rolled back.
scope.Complete();
}
}
catch (TransactionAbortedException ex)
{
writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message);
}
catch (ApplicationException ex)
{
writer.WriteLine("ApplicationException Message: {0}", ex.Message);
}
// Display messages.
Console.WriteLine(writer.ToString());
return returnValue;
}
只是一個想法,但你也許能夠使用TransactionAbortedException
抓來獲得實際的錯誤,忽略交易數量不匹配的警告。
@KM,你在樣本過程的早期有'IF @@ trancount <0'。 @@ trancount可以否定嗎?不應該;這是'IF @@ trancount = 0'? – 2010-12-07 20:37:59
@Charles Bretana,你是對的,它是一個類型o。我會修復它... – 2010-12-07 21:38:07
@KM,Thx!它在我的測試sproc中與變化一起工作,但是自從4月/ 5月以來這一直沒有受到干擾......所以我的自然假設是我錯過了一些東西......我並不完全確定這種方式或其他......快樂假期! – 2010-12-08 00:00:56