2017-04-18 84 views
2

我对触发器非常陌生,我似乎无法将我的头围绕在他们身上。假设我这里有两个表:创建在SQL Server中比较日期的触发器

CREATE TABLE Project 
(
    id INT NOT NULL IDENTITY(1, 1), 
    startDate DATETIME, 
    endDate DATETIME 
); 

CREATE TABLE Work 
(
    date DATETIME, 
    projectId INT 
); 

我插入一些数据:

INSERT INTO Project VALUES ('2017-04-18', '2017-05-01'); /*id = 1*/ 
INSERT INTO Work VALUES ('2017-04-17', 1); 

假设这里只有1 id = 1项目,这应该顺利。然而,我的工作在项目开始的前一天开始(在这种情况下并非如此)没有多大意义。我将如何创建基本上说date cannot be < startDate OR > endDate的触发器?

+1

你应该在应用层处理业务规则,而不是在数据库层。 –

+0

@WEI_DBA我知道。这完全不相关,我绝不会在真正的应用程序中这样做。 – MortenMoulder

+0

然后...在'Work'表上使用'而不是Insert Trigger'。 –

回答

2

像这样的东西应该工作:

CREATE TRIGGER t_CheckInterval ON dbo.Work 
    AFTER UPDATE, INSERT 
AS 

IF NOT EXISTS (
    --if no records are returned then work date lies outside the project 
    -- (start, end) interval 
    SELECT 1 
    FROM inserted AS i 
    JOIN Project AS p 
     ON p.Id = i.projectId AND i.[date] BETWEEN p.startDate AND p.endDate 
) 
BEGIN 
    RAISERROR ('Error: Your error message here.', 16, 1) 
    ROLLBACK TRANSACTION 
END 

GO 
+0

完美的作品!非常感谢。现在有更多的意义。我完全错过了JOIN部分。 – MortenMoulder

1

在你的情况,而不是使用触发器这几样checkings的,我建议使用检查约束,这样的事情:

CREATE FUNCTION dbo.ufn_CheckWorkDate 
(
    @WorkDate DateTime, 
    @ProjectID INT 
) 
RETURNS BIT 
AS 
BEGIN 
    DECLARE @Result BIT 

    IF EXISTS (SELECT * FROM Project WHERE id = @ProjectID AND @WorkDate BETWEEN startdate AND endDate) 
     SET @Result = 1 
    ELSE 
     SET @Result = 0 

    RETURN @Result 
END 

GO 

ALTER TABLE Work 
    WITH CHECK ADD CONSTRAINT CK_CheckWorkDate 
    CHECK (dbo.ufn_CheckWorkDate(date, projectid) = 1) 
+0

是的,使用触发器以外的其他东西(比如CONSTRAINT)绝对好得多。谢谢。 – MortenMoulder