1

条件を評価する関数を呼び出すテーブルに Check 制約があります。関数を直接呼び出すと、ダミー値に対して true が返されます。

挿入ステートメントを実行すると、チェック制約は、関数を直接呼び出すときに使用したのと同じ値に対して false を返します。

さらにチェックするには、チェック制約 (insert ステートメント) によって送信されたデータを SQL 関数にログ記録したいと考えています。

この場合、SQL プロファイラは役に立ちますか?

関数コード (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  

テーブル構造

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)))
4

1 に答える 1

1

問題は、レコードが挿入された後にチェック制約が評価されることです。これは、自己参照であるため、関数の戻り値を変更します。設定方法では、空のテーブルがある場合、テーブルにレコードを挿入することはできません。

これは、レコードが挿入されると

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

決して真実ではありません。そして、特定の従業員のために最初に挿入するとき

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

その従業員には他に記録がないため、決して真実になることはありません。ついに

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

テーブルにすでに欠席している日がある場合にのみtrueになります。最初の2つの条件が真にならないために、従業員に複数のレコードを挿入できない場合、3番目の条件は開始できません。

おそらく、最初の条件から(挿入されたばかりの)不在日を除外したいでしょう

NOT EXISTS (
  SELECT * 
  FROM absenteeism 
  WHERE  EMP_ID = @emp_ID 
    AND Absent_Date <> @leaveDate)
于 2011-12-06T23:53:26.513 に答える