我的主管要求我不要在此代码中放置事务和提交等,因为他说在此过程中放置事务是没用的。他经验丰富,我不能直接与他争辩,所以需要你的观点吗?
ALTER PROCEDURE [Employee].[usp_InsertEmployeeAdvances](
@AdvanceID BIGINT,
@Employee_ID INT,
@AdvanceDate DATETIME,
@Amount MONEY,
@MonthlyDeduction MONEY,
@Balance MONEY,
@SYSTEMUSER_ID INT,
@EntryDateTime DATETIME = NULL,
@ProcedureType SMALLINT)
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION [Trans1]
IF EXISTS
(
SELECT *
FROM Employee.Advance
WHERE AdvanceID = @AdvanceID
)
BEGIN
--UPDATION OF THE RECORD
IF @ProcedureType = 1
BEGIN
SET @Amount = @Amount * -1;
END
UPDATE Employee.Advance
SET
Employee_ID = @Employee_ID,
AdvanceDate = @AdvanceDate,
Amount = @Amount,
MonthlyDeduction = @MonthlyDeduction,
Balance = @Balance,
EntryDateTime = GETDATE()
WHERE AdvanceID = @AdvanceID
END
ELSE
BEGIN
DECLARE @LastRecordID INT
DECLARE @LastBalance MONEY
SET @LastRecordID =
(
SELECT MAX(EA.AdvanceID)
FROM Employee.Advance EA
WHERE EA.Employee_ID = @Employee_ID
)
SET @LastBalance =
(
SELECT EA.Balance
FROM Employee.Advance EA
WHERE EA.AdvanceID = ISNULL(@LastRecordID, 0)
)
IF(@ProcedureType = 0) --Advances
BEGIN
SET @Balance = ISNULL(@LastBalance, 0) + @Amount
INSERT INTO Employee.Advance
(Employee_ID,
AdvanceDate,
Amount,
MonthlyDeduction,
Balance,
User_ID,
EntryDateTime
)
VALUES
(@Employee_ID,
@AdvanceDate,
@Amount,
@MonthlyDeduction,
@Balance,
@SYSTEMUSER_ID,
GETDATE())
END
ELSE --Receivings
BEGIN
IF NOT EXISTS
(
SELECT *
FROM Employee.Advance EA
WHERE EA.Employee_ID = @Employee_ID
AND EA.Balance > 0
AND EA.AdvanceID =
(
SELECT MAX(AdvanceID)
FROM Advance
WHERE Employee_ID = @Employee_ID
)
)
BEGIN
RAISERROR('This Employee has no advances history', 16, 1)
RETURN
--Select 0
END
ELSE
BEGIN
SET @Balance = ISNULL(@LastBalance, 0) - @Amount
INSERT INTO Employee.Advance
(Employee_ID,
AdvanceDate,
Amount,
MonthlyDeduction,
Balance,
User_ID,
EntryDateTime
)
VALUES
(@Employee_ID,
@AdvanceDate,
-1 * @Amount,
@MonthlyDeduction,
@Balance,
@SYSTEMUSER_ID,
GETDATE())
END
END
END
COMMIT TRANSACTION [Trans1]
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION [Trans1]
END CATCH
END
答案 0 :(得分:1)
ALTER PROCEDURE [Employee].[usp_InsertEmployeeAdvances]
(
@AdvanceID BIGINT,
@Employee_ID INT,
@AdvanceDate DATETIME,
@Amount MONEY,
@MonthlyDeduction MONEY,
@Balance MONEY,
@SYSTEMUSER_ID INT,
@EntryDateTime DATETIME = NULL,
@ProcedureType SMALLINT
)
AS BEGIN
SET NOCOUNT ON
IF EXISTS (
SELECT 1
FROM Employee.Advance
WHERE AdvanceID = @AdvanceID
)
BEGIN
UPDATE Employee.Advance
SET
Employee_ID = @Employee_ID,
AdvanceDate = @AdvanceDate,
Amount = CASE WHEN @ProcedureType = 1 THEN -@Amount ELSE @Amount END,
MonthlyDeduction = @MonthlyDeduction,
Balance = @Balance,
EntryDateTime = GETDATE()
WHERE AdvanceID = @AdvanceID
END
ELSE BEGIN
DECLARE
@LastRecordID INT
, @LastBalance MONEY
, @IsBalance BIT
SELECT @LastRecordID = MAX(AdvanceID)
FROM Employee.Advance
WHERE Employee_ID = @Employee_ID
SELECT
@LastBalance = Balance,
@IsBalance = CASE WHEN Balance > 0 THEN 1 ELSE 0 END
FROM Employee.Advance
WHERE AdvanceID = ISNULL(@LastRecordID, 0)
IF ISNULL(@IsBalance, 0) = 0 BEGIN
RAISERROR('This Employee has no advances history', 16, 1)
RETURN
END
ELSE BEGIN
INSERT INTO Employee.Advance(Employee_ID, AdvanceDate, Amount, MonthlyDeduction, Balance, [User_ID], EntryDateTime)
SELECT
@Employee_ID,
@AdvanceDate,
CASE WHEN @ProcedureType = 0 THEN @Amount ELSE -@Amount END,
@MonthlyDeduction,
ISNULL(@LastBalance, 0) + CASE WHEN @ProcedureType = 0 THEN @Amount ELSE -@Amount END,
@SYSTEMUSER_ID,
GETDATE()
END
END
END
答案 1 :(得分:1)
这是一个改变了的答案,因为我没有读完整个问题
如果没有交易,如果同时调用并且记录不存在那么两者都可以插入,而且可能会出现@Balance错误
是的,交易有用的目的
答案 2 :(得分:0)
我从不把交易放在特定的工作中,因为你永远不知道它什么时候会被合并到另一个工作中。只有来电者才能知道。要使用陈旧的示例,您可能会认为创建订单和添加项目应该是一个足够公平的交易。在轨道下方,某些呼叫功能可能希望将信用检查或帐户创建的结果作为其一部分包括在内。所以基本上在低级别你不能知道*如果你在交易的背景下或不是这样,那么对提交的严格要求就没那么重要了。同样,回滚有点不对 - 你永远不知道在调用者的上下文中特定错误是多么致命,所以只需抛出异常并让客户决定如何管理它。
*你可以,但通常更容易不关心。
答案 3 :(得分:0)
由于现在正在编写存储过程,因此事务不会添加任何内容。只有其中一个修改会运行,如果它失败,那么无论如何它都会回滚。另外值得注意的是,在修改后没有任何反应。如果在其中一个更新后有一些额外的代码,则可能需要进行交易。
然而,进行该交易的成本是多少?您是否期望此代码永远不会改变?未来的变化可能会使交易变得必要,而不会显而易见。鉴于您的存储过程的性质,我发现很难相信交易存在缺点。
要处理RAISERROR
区块内的TRY..CATCH
:
BEGIN TRANSACTION
BEGIN TRY
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF (@@TRANCOUNT > 0)
ROLLBACK TRANSACTION
EXEC dbo.LogErrorAndRethrow
END CATCH
LogErrorAndRethrow
的代码如下:
CREATE PROCEDURE dbo.LogErrorAndRethrow
@LogError BIT = 1
AS
BEGIN
DECLARE
@error_number INT,
@error_message NVARCHAR(MAX),
@error_severity INT,
@error_state INT,
@error_procedure NVARCHAR(200),
@error_line INT
SELECT
@error_number = ERROR_NUMBER(),
@error_message = ERROR_MESSAGE(),
@error_severity = ERROR_SEVERITY(),
@error_state = ERROR_STATE(),
@error_procedure = COALESCE(ERROR_PROCEDURE(), '<Unknown>'),
@error_line = ERROR_LINE()
IF (@LogError = 1)
BEGIN
EXEC dbo.InsertAuditLog
@UserID = 0,
@AuditType = 'Error',
@ModuleName = @error_procedure,
@Message = @error_message
END
-- Rebuild the error message with parameters so that all information appears in the RAISERROR
SELECT @error_message = N'Error %d, Level %d, State %d, Procedure %s, Line %d, ' + 'Message: ' + ERROR_MESSAGE()
RAISERROR(@error_message, @error_severity, 1, @error_number, @error_severity, @error_state, @error_procedure, @error_line)
END
InsertAuditLog
基本上只是插入日志表。