使用存储过程的薪水 PAYE 括号
Salary PAYE brackets using a stored procedure
我正在尝试插入 Employee
table,我希望 if 语句插入 Salary
、NetSalary
和 Deduction
如果 Employee
将根据小时费率赚取一定数量的列。
如果语句是为了在金额落入特定括号时将数据插入相关列
ALTER PROCEDURE [dbo].[spSaveEmployee]
(@EmployeePersonName Varchar(20),
@JobTitle int,
@Branch int,
@Department int,
@Manager int,
@HourlyRate MONEY,
@PaymentDate datetime = '2021-10-05 00:00:00.000',
@ErrorMessage Varchar(50) OUTPUT)
AS
BEGIN
DECLARE @DefaultDate DATETIME = GETDATE()
--DECLARE @PAYE INT
--SET @PAYE = 26 / 100
DECLARE @Salary INT
--SET @Salary = @HourlyRate * 180
--DECLARE @PYE INT
--SET @PYE = 1.15
DECLARE @NetSalary MONEY
DECLARE @Deduction DECIMAL (18,2)
DECLARE @NetSalary1 MONEY
DECLARE @NetSalary2 MONEY
DECLARE @NetSalary3 MONEY
--SET @NetSalary = @Salary - @PYE
DECLARE @Deduction1 DECIMAL (18,2)
DECLARE @Deduction2 DECIMAL (18,2)
DECLARE @Deduction3 DECIMAL (18,2)
SET @Deduction1 = (@Salary * 18) / 100
SET @NetSalary1 = @Salary - @Deduction1
SET @Deduction2 = (@Salary * 26) / 100
SET @NetSalary2 = @Salary - @Deduction2
SET @Deduction3 = (@Salary * 31) / 100
SET @NetSalary3 = @Salary - @Deduction3
IF NOT EXISTS (SELECT * FROM EmployeeBook
WHERE EmployeePersonName = @EmployeePersonName)
BEGIN
INSERT INTO EmployeeBook (EmployeePersonName, JobTitle, Branch, Department,
Manager, HourlyRate, PAYE_Tax, Salary,
NetSalary, PaymentDate, Deductions)
VALUES (@EmployeePersonName, @JobTitle, @Branch, @Department,
@Manager, @HourlyRate, 1.15, @Salary,
@NetSalary, @DefaultDate, @Deduction)
SET @ErrorMessage = ''
IF @Salary <= 321000
BEGIN
SELECT @Deduction = @Deduction
SELECT @NetSalary = @NetSalary
END
ELSE IF @Salary >= 321001 AND @Salary <= 445100
BEGIN
SELECT @Deduction = @Deduction2
SELECT @NetSalary = @NetSalary2
END
ELSE IF @Salary >= 445100 AND @Salary <= 584200
BEGIN
SELECT @Deduction = @Deduction3
SELECT @NetSalary = @NetSalary3
END
END
ELSE
BEGIN
SET @EmployeePersonName = ''
SET @JobTitle = 0
SET @Branch = 0
SET @Department = 0
SET @Manager = 0
SET @HourlyRate = 0.00
SET @Salary = 0.00
SET @NetSalary = 0.00
SET @PaymentDate = @DefaultDate
SET @Deduction = 0
SET @ErrorMessage = 'Sorry could not save ' + @EmployeePersonName + ' Employee name already exists'
END
END
GO
以下是我认为您正在努力完成的工作。问题和评论:
- 您在使用变量后对其进行设置 - 因此它们无效。
- T-SQL 针对基于集合的操作进行了优化,因此您应该尽可能尝试以基于集合的方式执行操作,而不是程序性的
- 最佳做法是为 T-SQL
使用一致的大小写
- 正如 Larnu 指出的那样,错误处理最好使用 throw 来处理。
- 最佳做法是始终为数据库对象添加架构前缀
- SP 应始终有一个 return 声明
- SP 应该正常启动
SET NOCOUNT, XACT_ABORT ON;
- 既然你可以立即验证此人的存在,我会节省任何进一步的处理时间。
- 如果薪水超出定义的范围怎么办?您可能不期望它,但您应该处理它,因此
CASE
表达式中的 ELSE
。
- 我会避免在您的 SP 前加上
sp
前缀,因为它太接近系统前缀 sp_
。事实上,为什么要给它们加上前缀?
- 像这样创建括号时,一个结束条件需要是
less than or equal
,另一个条件是 greater than
(反之亦然),以避免值落入 2 个括号中。尽管case
会短路到第一个匹配的表达式,但从理解的角度来看,最好有正确和准确的逻辑。
ALTER PROCEDURE [dbo].[SaveEmployee]
(
@EmployeePersonName VARCHAR(20),
@JobTitle INT,
@Branch INT,
@Department INT,
@Manager INT,
@HourlyRate MONEY,
@PaymentDate DATETIME = '2021-10-05 00:00:00.000',
@ErrorMessage VARCHAR(50) OUTPUT
)
AS
BEGIN
SET NOCOUNT, XACT_ABORT ON;
IF EXISTS (SELECT 1 FROM dbo.EmployeeBook WHERE EmployeePersonName = @EmployeePersonName) BEGIN
SET @ErrorMessage = 'Sorry could not save ' + @EmployeePersonName + ' Employee name already exists' END
RETURN;
-- Comment out 2 lines above to uncomment the 2 code line below
-- As suggested by Larnu, this would be more a typical error handling approach
--DECLARE @Error NVARCHAR(2048) = 'Sorry could not save ' + @EmployeePersonName + ' Employee name already exists';
--THROW 51000, @Error, 1;
END;
DECLARE @DefaultDate DATETIME = GETDATE(), @Salary INT = @HourlyRate * 180;
INSERT INTO dbo.EmployeeBook (EmployeePersonName, JobTitle, Branch, Department
, Manager, HourlyRate, PAYE_Tax, Salary
, NetSalary, PaymentDate, Deductions)
SELECT EmployeePersonName, JobTitle, Branch, Department
, Manager, HourlyRate, 1.15, Salary
, CASE SalaryBracket WHEN 1 THEN Salary - Deduction1
WHEN 2 THEN Salary - Deduction2
WHEN 3 THEN Salary - Deduction3
-- ELSE ??
END
, @DefaultDate
, CASE SalaryBracket WHEN 1 THEN Deduction1
WHEN 2 THEN Deduction2
WHEN 3 THEN Deduction3
-- ELSE ??
END
FROM (
VALUES (@EmployeePersonName, @JobTitle, @Branch, @Department, @Manager, @HourlyRate, 1.15, @Salary
, (@Salary * 18) / 100, (@Salary * 26) / 100, (@Salary * 31) / 100
-- Compute Salary Bracket in one place for reuse
, CASE WHEN @Salary <= 321000 THEN 1
WHEN @Salary > 321001 AND @Salary <= 445100 THEN 2
WHEN @Salary > 445100 AND @Salary <= 584200 THEN 3 END
)
) AS X (EmployeePersonName, JobTitle, Branch, Department, Manager, HourlyRate, PAYE_Tax, Salary, Deduction1, Deduction2, Deduction3, SalaryBracket);
RETURN 0;
END
GO
我正在尝试插入 Employee
table,我希望 if 语句插入 Salary
、NetSalary
和 Deduction
如果 Employee
将根据小时费率赚取一定数量的列。
如果语句是为了在金额落入特定括号时将数据插入相关列
ALTER PROCEDURE [dbo].[spSaveEmployee]
(@EmployeePersonName Varchar(20),
@JobTitle int,
@Branch int,
@Department int,
@Manager int,
@HourlyRate MONEY,
@PaymentDate datetime = '2021-10-05 00:00:00.000',
@ErrorMessage Varchar(50) OUTPUT)
AS
BEGIN
DECLARE @DefaultDate DATETIME = GETDATE()
--DECLARE @PAYE INT
--SET @PAYE = 26 / 100
DECLARE @Salary INT
--SET @Salary = @HourlyRate * 180
--DECLARE @PYE INT
--SET @PYE = 1.15
DECLARE @NetSalary MONEY
DECLARE @Deduction DECIMAL (18,2)
DECLARE @NetSalary1 MONEY
DECLARE @NetSalary2 MONEY
DECLARE @NetSalary3 MONEY
--SET @NetSalary = @Salary - @PYE
DECLARE @Deduction1 DECIMAL (18,2)
DECLARE @Deduction2 DECIMAL (18,2)
DECLARE @Deduction3 DECIMAL (18,2)
SET @Deduction1 = (@Salary * 18) / 100
SET @NetSalary1 = @Salary - @Deduction1
SET @Deduction2 = (@Salary * 26) / 100
SET @NetSalary2 = @Salary - @Deduction2
SET @Deduction3 = (@Salary * 31) / 100
SET @NetSalary3 = @Salary - @Deduction3
IF NOT EXISTS (SELECT * FROM EmployeeBook
WHERE EmployeePersonName = @EmployeePersonName)
BEGIN
INSERT INTO EmployeeBook (EmployeePersonName, JobTitle, Branch, Department,
Manager, HourlyRate, PAYE_Tax, Salary,
NetSalary, PaymentDate, Deductions)
VALUES (@EmployeePersonName, @JobTitle, @Branch, @Department,
@Manager, @HourlyRate, 1.15, @Salary,
@NetSalary, @DefaultDate, @Deduction)
SET @ErrorMessage = ''
IF @Salary <= 321000
BEGIN
SELECT @Deduction = @Deduction
SELECT @NetSalary = @NetSalary
END
ELSE IF @Salary >= 321001 AND @Salary <= 445100
BEGIN
SELECT @Deduction = @Deduction2
SELECT @NetSalary = @NetSalary2
END
ELSE IF @Salary >= 445100 AND @Salary <= 584200
BEGIN
SELECT @Deduction = @Deduction3
SELECT @NetSalary = @NetSalary3
END
END
ELSE
BEGIN
SET @EmployeePersonName = ''
SET @JobTitle = 0
SET @Branch = 0
SET @Department = 0
SET @Manager = 0
SET @HourlyRate = 0.00
SET @Salary = 0.00
SET @NetSalary = 0.00
SET @PaymentDate = @DefaultDate
SET @Deduction = 0
SET @ErrorMessage = 'Sorry could not save ' + @EmployeePersonName + ' Employee name already exists'
END
END
GO
以下是我认为您正在努力完成的工作。问题和评论:
- 您在使用变量后对其进行设置 - 因此它们无效。
- T-SQL 针对基于集合的操作进行了优化,因此您应该尽可能尝试以基于集合的方式执行操作,而不是程序性的
- 最佳做法是为 T-SQL 使用一致的大小写
- 正如 Larnu 指出的那样,错误处理最好使用 throw 来处理。
- 最佳做法是始终为数据库对象添加架构前缀
- SP 应始终有一个 return 声明
- SP 应该正常启动
SET NOCOUNT, XACT_ABORT ON;
- 既然你可以立即验证此人的存在,我会节省任何进一步的处理时间。
- 如果薪水超出定义的范围怎么办?您可能不期望它,但您应该处理它,因此
CASE
表达式中的ELSE
。 - 我会避免在您的 SP 前加上
sp
前缀,因为它太接近系统前缀sp_
。事实上,为什么要给它们加上前缀? - 像这样创建括号时,一个结束条件需要是
less than or equal
,另一个条件是greater than
(反之亦然),以避免值落入 2 个括号中。尽管case
会短路到第一个匹配的表达式,但从理解的角度来看,最好有正确和准确的逻辑。
ALTER PROCEDURE [dbo].[SaveEmployee]
(
@EmployeePersonName VARCHAR(20),
@JobTitle INT,
@Branch INT,
@Department INT,
@Manager INT,
@HourlyRate MONEY,
@PaymentDate DATETIME = '2021-10-05 00:00:00.000',
@ErrorMessage VARCHAR(50) OUTPUT
)
AS
BEGIN
SET NOCOUNT, XACT_ABORT ON;
IF EXISTS (SELECT 1 FROM dbo.EmployeeBook WHERE EmployeePersonName = @EmployeePersonName) BEGIN
SET @ErrorMessage = 'Sorry could not save ' + @EmployeePersonName + ' Employee name already exists' END
RETURN;
-- Comment out 2 lines above to uncomment the 2 code line below
-- As suggested by Larnu, this would be more a typical error handling approach
--DECLARE @Error NVARCHAR(2048) = 'Sorry could not save ' + @EmployeePersonName + ' Employee name already exists';
--THROW 51000, @Error, 1;
END;
DECLARE @DefaultDate DATETIME = GETDATE(), @Salary INT = @HourlyRate * 180;
INSERT INTO dbo.EmployeeBook (EmployeePersonName, JobTitle, Branch, Department
, Manager, HourlyRate, PAYE_Tax, Salary
, NetSalary, PaymentDate, Deductions)
SELECT EmployeePersonName, JobTitle, Branch, Department
, Manager, HourlyRate, 1.15, Salary
, CASE SalaryBracket WHEN 1 THEN Salary - Deduction1
WHEN 2 THEN Salary - Deduction2
WHEN 3 THEN Salary - Deduction3
-- ELSE ??
END
, @DefaultDate
, CASE SalaryBracket WHEN 1 THEN Deduction1
WHEN 2 THEN Deduction2
WHEN 3 THEN Deduction3
-- ELSE ??
END
FROM (
VALUES (@EmployeePersonName, @JobTitle, @Branch, @Department, @Manager, @HourlyRate, 1.15, @Salary
, (@Salary * 18) / 100, (@Salary * 26) / 100, (@Salary * 31) / 100
-- Compute Salary Bracket in one place for reuse
, CASE WHEN @Salary <= 321000 THEN 1
WHEN @Salary > 321001 AND @Salary <= 445100 THEN 2
WHEN @Salary > 445100 AND @Salary <= 584200 THEN 3 END
)
) AS X (EmployeePersonName, JobTitle, Branch, Department, Manager, HourlyRate, PAYE_Tax, Salary, Deduction1, Deduction2, Deduction3, SalaryBracket);
RETURN 0;
END
GO