我有两个存储过程,一个嵌套在另一个中。当调用嵌套存储过程时,此时它应该在出现外键约束冲突时出错,然后回滚先前的insert以插入到ProductLicense表中。嵌套过程不会对数据库执行任何操作,因为外键违规但调用存储过程没有捕获错误并回滚。如果我自己执行嵌套存储过程,它会返回错误547外键冲突。
如何让两个存储过程协同工作?
外部程序:
ALTER PROCEDURE [dbo].[AddNewLicense2_i]
-- Add the parameters for the stored procedure here
@customerId nvarchar(10),
@licenseModeId int,
@licenseModeProgramId int,
@createdBy int,
@updateBy int,
@systemId nvarchar(50),
@productId int
AS
BEGIN TRY
BEGIN TRANSACTION
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--SET XACT_ABORT ON; --used for automatic rollback when an error occurs
DECLARE @tempDays INT
DECLARE @programCornerAmt INT
DECLARE @tempEndDate DATETIME
DECLARE @tempExpDate DATETIME
DECLARE @err INT
SET @err = 0
/*SET @tempDays = (SELECT lmp.TimeoutDays
FROM LicenseModeProgram lmp
WHERE lmp.LicenseModeProgramId = @licenseModeProgramId)*/
SELECT @tempDays = TimeoutDays, @programCornerAmt = MonthlyCornersAmount
FROM LicenseModeProgram
WHERE LicenseModeProgramId = @licenseModeProgramId
--Build Expiration and End Dates.
IF @tempDays = NULL --then this is NOT a time rental or metered system
BEGIN
SET @tempEndDate = NULL
SET @tempExpDate = NULL
END
ELSE
BEGIN
SET @tempEndDate = DATEADD("d", @tempDays, GETDATE())
SET @tempExpDate = DATEADD("d", @tempDays, GETDATE())
END
-- Create new product license record
INSERT INTO ProductLicense (CustomerId, LicenseModeId, LicenseModeProgramId, CreatedBy, UpdatedBy, SystemId, ProductId, ExpirationDate, LicenseEndDate)
VALUES (@customerId, @licenseModeId, @licenseModeProgramId, @createdBy, @updateBy, @systemId, @productId, @tempExpDate, @tempEndDate)
IF @licenseModeId = 4 AND @systemId NULL AND @programCornerAmt NULL
--call stored procedure to add corners to the customer account
EXECUTE @err = AddMeteredTx_i @systemId, 1, 1, @programCornerAmt , 'Initial License Creation'
PRINT @err
COMMIT TRANSACTION
END TRY
BEGIN CATCH
RAISERROR('Failed to Create License', 11, 2)
ROLLBACK TRANSACTION
RETURN 1
END CATCH
--COMMIT TRANSACTION
RETURN 0
GO
内部程序:
ALTER PROCEDURE [dbo].[AddMeteredTx_i]
-- Add the parameters for the stored procedure here
@systemId nvarchar(50),
@activityEventId int,
@createdBy int,
@amount int,
@notes text
AS
BEGIN TRY
BEGIN TRANSACTION
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--SET XACT_ABORT ON; --used for automatic rollback when an error occurs
INSERT INTO CustomerAccountActivity (SystemId, ActivityEventId, CreatedBy, Amount, Notes)
VALUES (@systemId, @activityEventId, @createdBy, @amount, @notes)
UPDATE CustomerAccount
SET MeteredBalance = (SELECT MeteredBalance FROM CustomerAccount WHERE SystemId = @systemId) + @amount
WHERE SystemId = @systemId
COMMIT TRANSACTION
END TRY
BEGIN CATCH
RAISERROR('Error Update to Customer Account Record ', 11, 2)
ROLLBACK TRANSACTION
RETURN 1
--COMMIT TRANSACTION
END CATCH
RETURN 0
GO
答案 0 :(得分:6)
使用@@Error
使用这样的调用堆栈捕获错误可能会有问题。使用TRY/CATCH
基本格式为:
BEGIN TRY
<BEGIN TRAN>
... do stuff ...
<COMMIT TRAN>
END TRY
BEGIN CATCH
<ROLLBACK TRAN>
... do error stuff like re-raise the error to outer scope ...
END CATCH
尝试中遇到的任何错误都会自动将您带到CATCH块而无需额外检查。