Question

I have a Check constraint on a table which calls a function to evaluate a condition. When I directly calls a functions, it does return me true for the dummy values.

When I run an insert statement , check constraint returns me false for same values which I used in directly calling a function .

To check it further, I want to LOG the data sent by check constraint (on insert statement) to the SQL function.

Will SQL Profiler help me in this case ?

Here is the function code (T-SQL)

CREATE FUNCTION [dbo].[fn_CheckLeaveContinuation] (@emp_Id        INT,
                                                   @leaveDate     DATETIME,
                                                   @severityPoint INT)
RETURNS BIT
AS
  BEGIN
      --For the given  emp_id and the leave date, check if the given employee 
      -- has already taken a leave on the previous day. Leaves in continuation 
      -- should have severity point as Zero else return false
      DECLARE @isLeaveContinued BIT;

      --if it's a first leave of the employee then return true 
      SELECT @isLeaveContinued= 
            CASE
               WHEN NOT EXISTS (SELECT *
                                FROM   absenteeism
                                WHERE  EMP_ID = @emp_ID)
                    OR EXISTS (SELECT *
                               FROM   absenteeism
                               WHERE  DateDiff(DAY, @leaveDate, Absent_Date) = -1
                                       AND EMP_ID = @emp_ID)
                        AND @severityPoint = 0
                    OR EXISTS (SELECT *
                               FROM   Absenteeism
                               WHERE  DateDiff(DAY, @leaveDate, Absent_Date) < -1
                               )
             THEN
               'true'
               ELSE 'false'
             END

      RETURN @isLeaveContinued
  END  

Table Structure

CREATE TABLE [dbo].[Absenteeism](
    [EMP_ID] [int] NOT NULL,
    [Absent_date] [datetime] NOT NULL,
    [Reason_code] [char](40) NOT NULL,
    [Severity_Points] [int] NOT NULL
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[Absenteeism]  WITH CHECK ADD  CONSTRAINT [chk_Leave_Continuation] CHECK  (([dbo].[fn_CheckLeaveContinuation]([Emp_ID],[Absent_date],[Severity_Points])='true'))
GO
ALTER TABLE [dbo].[Absenteeism] CHECK CONSTRAINT [chk_Leave_Continuation]
GO
ALTER TABLE [dbo].[Absenteeism]  WITH CHECK ADD CHECK  (([severity_points]>=(0) AND [severity_points]<=(4)))
Was it helpful?

Solution

The problem is the check constraint is evaluated after the record has been inserted, which alters the return value of the function due to it being self referential. The way it is set up, if you have an empty table, it is impossible to insert any records in the table.

This is because once a record is inserted

NOT EXISTS (SELECT * FROM absenteeism WHERE  EMP_ID = @emp_ID)

will never be true. And when first inserting for a particular employee

EXISTS (
  SELECT * 
  FROM absenteeism2
  WHERE  DateDiff(DAY, @leaveDate, Absent_Date) = -1
    AND EMP_ID = @emp_ID)

can never be true as there is no other record for that employee. Finally

EXISTS (
  SELECT *
  FROM Absenteeism2
  WHERE DateDiff(DAY, @leaveDate, Absent_Date) < -1
)

can only be true if there are already absent days prior in the table. If you can't insert more than one record for an employee because the first two conditions can't be true, the third condition can never kick in.

Perhaps you want to exclude the (just inserted) absent day from the first condition

NOT EXISTS (
  SELECT * 
  FROM absenteeism 
  WHERE  EMP_ID = @emp_ID 
    AND Absent_Date <> @leaveDate)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top