2012-12-02 109 views
3

一位學生正在去一所學校,每月支付一筆價值。該值會被(FatherSalary + MotherSalary)*0.05CREATE TRIGGER - SQL SERVER

我纔開始學習的觸發器,昨天我做了一個,但我得到了錯誤

消息515,級別16,狀態2,過程TR_Calc_Value,第25行
不能將NULL值插入列「IDStudent」,表「HW32.dbo.Enrollment」;列不允許空INSERT失敗

當我在表Enrollment插入值任何幫助如何解決此問題。 ?

USE master; 

IF DB_ID (N'HW32') IS NOT NULL 
    DROP DATABASE HW32; 

CREATE DATABASE HW32; 

USE HW32 
CREATE TABLE Family(
    IDFamily int IDENTITY(1,1), 
    FirstName nchar(20) NOT NULL, 
    LastName nchar(20) NOT NULL, 
    Gender nchar(1) NOT NULL, 
    Salary money, 
    CONSTRAINT PK_Family PRIMARY KEY(IDFamily), 
    CONSTRAINT CK_Family_Gender CHECK (Gender IN ('M','F')) 
) 

CREATE TABLE Student(
    IDStudent int IDENTITY(1,1), 
    FirstName nchar(20) NOT NULL, 
    LastName nchar(20) NOT NULL, 
    CONSTRAINT PK_Student PRIMARY KEY(IDStudent) 
) 

CREATE TABLE Filiation(
    IDStudent int, 
    IDFamily int, 
    Filiation nchar(20) NOT NULL, 
    CONSTRAINT FK_Filiation_IDStudent FOREIGN KEY (IDStudent) 
    REFERENCES Student(IDStudent), 
    CONSTRAINT FK_Filiation_IDFamily FOREIGN KEY (IDFamily) 
    REFERENCES Family(IDFamily), 
    CONSTRAINT PK_Filiation PRIMARY KEY(IDStudent,IDFamily) 
) 

CREATE TABLE Enrollment(
    IDEnrollment int IDENTITY(1,1), 
    IDStudent int NOT NULL, 
    Status nchar(20) NOT NULL, 
    MonthlyPayment money, 
    CONSTRAINT PK_Enrollment PRIMARY KEY(IDStudent), 
    CONSTRAINT FK_Enrollment_IDStudent FOREIGN KEY (IDStudent) 
    REFERENCES Student(IDStudent), 
    CONSTRAINT CK_Enrollment_Status CHECK(Status IN('Acepted','Rejected')), 
    CONSTRAINT UC_Enrollment UNIQUE (IDEnrollment) 
) 

USE HW32 
GO 
CREATE TRIGGER TR_Calc_Value 
ON Enrollment 
AFTER INSERT, UPDATE AS 
    DECLARE @monthlyPayment money, @sFather money, @sMother money 
BEGIN 
    SET @sFather = (SELECT FAM.Salary 
      FROM Family FAM 
      LEFT JOIN Filiation F ON F.IDFamily = FAM.IDFamily 
      LEFT JOIN inserted I ON I.IDStudent = F.IDStudent 
      WHERE F.IDStudent = I.IDStudent AND FAM.Gender = 'M') 

    SET @sMother = (SELECT FAM.Salary 
      FROM Family FAM 
      LEFT JOIN Filiation F ON F.IDFamily = FAM.IDFamily 
      LEFT JOIN inserted I ON I.IDStudent = F.IDStudent 
      WHERE F.IDStudent = I.IDStudent AND FAM.Gender = 'F') 

    SET @monthlyPayment = ((@sFather + @sMother) * 0.05) 

    INSERT INTO Enrollment (MonthlyPayment) VALUES (@monthlyPayment) 
END 
GO 

USE HW32 
INSERT INTO Family VALUES('John', 'Smith', 'M', 800) 
INSERT INTO Family VALUES('Anna', 'Smith', 'F', 800) 

INSERT INTO Student VALUES('Carl', 'Smith') 

INSERT INTO Filiation VALUES(1, 1, 'Father') 
INSERT INTO Filiation VALUES(1, 2, 'Mother') 

INSERT INTO Enrollment (IDStudent, Status) VALUES(1, 'Accepted') 
+1

是否有存儲此信息的原因。似乎只要您需要查詢,視圖就可以執行此計算。此外,你的觸發器被破壞 - 「插入」是一個僞表。它可能包含*多個*行。因此,將使用它的查詢結果分配給標量變量幾乎總是錯誤的。 –

+0

請在您的觸發器中看到INSERT:'Enrollment'表中的兩個NOT NULL列'IDStudent'和'Status'沒有被填充 - 這就是導致錯誤信息的原因。你將它們定義爲NOT NULL,並且你沒有定義任何默認值 - 在這種情況下,你必須爲每個INSERT語句中的這兩列**提供值到** Enrollment中表 –

+0

昨晚一位朋友給出了這個觸發器,但他只是通過電子郵件向我發送了代碼,並沒有向我解釋如何使用它,我做了一些改變,但我不知道插入的是什麼。解決方案如下,謝謝你的答覆,並感謝下面的用戶提供解決方案。 – wormwood87

回答

6

你不想INSERT在觸發一排 - 行已添加。相反,你要執行UPDATE

CREATE TRIGGER TR_Calc_Value ON Enrollment AFTER INSERT, UPDATE AS 
BEGIN 
    UPDATE E 
    set MonthlyPayment = (

     select 0.05 * SUM(Salary) 
     from Family FAM 
     inner join Filiation F 
     on FAM.IDFamily= F.IDFamily 
     where F.IDStudent = I.IDStudent 
    ) 

    from Enrollment E 
    inner join inserted I 
    on E.IDEnrollment= I.IDEnrollment 

需要注意的事項

  • 以上適當使用含有多行
  • 我沒有父親和母親之間的區別(因爲inserted科佩斯他們似乎被一視同仁)
  • 如果有多個父親和母親與該學生相關聯,他們都包括在內。這是否正確是值得商榷的,並且可能無法實現更好的約束 - 但最初的觸發器並不能很好地應對這種情況。

按我的意見,我也建議存儲這些信息,如果它總是可以從其他表(不知道這是正確的在這種情況下,重新計算,但如果它應該反映了其他表格,你需要更多的觸發器來保持一切的一致性

而且作爲per-marc的刪除答案,它也將是一個好習慣,讓你總是指定列列表時做插入,這不是造成這種特殊錯誤的原因,但有助於記錄你的意圖r並通過視覺檢查幫助快速消除可能的錯誤。

+0

此外 - 當應該發生INSERT時,Enrollment表中的兩個NOT NULL列IDStudent和Status不會被該語句填充(這就是導致錯誤消息的原因第一名) –

+0

非常感謝你!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!有效!!!!!!!!!!!!!!!!!!!!! – wormwood87