有一个大规模升级到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