2017-04-18 2 views
2

Ich bin sehr neu zu Triggern und ich kann nicht scheinen, meinen Kopf um sie zu wickeln. Nehmen sie an, ich habe zwei Tabellen hier:Erstellen Sie Trigger, die Daten in SQL Server vergleicht

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

CREATE TABLE Work 
(
    date DATETIME, 
    projectId INT 
); 

ich einige Daten einfügen:

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

Unter der Annahme, es gibt nur ein Projekt mit id = 1, soll dieser gut gehen. Es macht jedoch wenig Sinn, dass meine Arbeit am Tag vor dem Projektstart beginnt (nicht in diesem Fall). Wie würde ich einen Trigger erstellen, der im Grunde sagt date cannot be < startDate OR > endDate?

+1

Sie sollen Handle Geschäftsregeln auf der Anwendungsebene, nicht auf der Datenbankebene. –

+0

@WEI_DBA Ich weiß. Das ist überhaupt keine Arbeit, und ich würde das nie in einer realen Anwendung machen. – MortenMoulder

+0

Dann ... Verwenden Sie einen "anstelle von Insert Trigger" in der Tabelle "Arbeit". –

Antwort

2

So etwas wie dies funktionieren soll:

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

Funktioniert perfekt! Danke vielmals. Machen Sie jetzt viel mehr Sinn. Ich habe den JOIN Teil komplett vermisst. – MortenMoulder

1

In Ihrem Fall statt für diese Art von checkings Trigger, schlage ich vor, eine Check-Constraint zu verwenden, etwa so:

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

Ja, mit etwas anderem als einem Trigger (wie einem CONSTRAINT) ist definitiv viel besser. Vielen Dank. – MortenMoulder