We have some business rules that enforce things such as Employee's can only have one current activity (Todo, In-Progress), and all others must be a different State (Completed, Removed)
We've noticed that sometimes we get duplicate activities entered into the database even though our business rules should prevent it (we check for an active one before inserting). We think its a small timing issue (both are adding at the exact same time from two different sources)
Would we be able to use a check constraint?
The business rules are:
- One Employee (Id) per activity type (ActivityId) with activity state that is active (0 or 1)
So two employees can each be doing an activity and have it active, or a single employee can have multiple of the same activity as long as only one of them is active at a time (others can be in state 2 / 3)
- EmployeeId 1 Activity 1 State 1 exists in database
- adding EmployeeId 1 Activity 1 State 0 would fail
- adding EmployeeId 1 Activity 2 State 0 would succeed
- adding EmployeeId 2 Activity 1 State 0 would succeed
Once the existing record gets updated to state 2 or 3 then the employee would again be able to add a new record in todo/in progress state.
So can this type of logic be placed in a SQL Server check constraint or do we need to use a trigger or something after the fact to remove these "duplicates"?
Edit:
Here is the function I have but its erroring on everything I try to insert (returns 1 or 0 correctly when run outside of the constraint):
I had to alter the function to accept an Id to ignore, as the check constraint was failing because it found the record it was inserting!
ALTER FUNCTION [dbo].[ActiveEmployeeActivitiyExists]
(
-- Add the parameters for the function here
@ActivityId nvarchar(5),
@EmployeeId int,
@IgnoreId int,
)
RETURNS int
AS
BEGIN
DECLARE @Id int
SELECT Top(1) @Id = Id
FROM [dbo].[EmployeeActivities]
WHERE EmployeeId = @EmployeeId and ActivityId = @ActivityId and ActivityState < 2 and Id <> @IgnoreId
RETURN CASE WHEN(@Id IS NULL) THEN 0 ELSE 1 END
END