简体   繁体   English

创建TRIGGER - SQL SERVER

[英]CREATE TRIGGER - SQL SERVER

A student is going to a school where he's going to pay a monthly value. 一名学生将去一所学校,在那里他将支付每月的价值。 That value will be ( FatherSalary + MotherSalary)*0.05 那个值将是( FatherSalary + MotherSalary)*0.05

I only started to study triggers yesterday, I made one but i got the error 我昨天才开始研究触发器,我做了一个,但我得到了错误

Msg 515, Level 16, State 2, Procedure TR_Calc_Value, Line 25 消息515,级别16,状态2,过程TR_Calc_Value,第25行
Cannot insert the value NULL into column 'IDStudent', table 'HW32.dbo.Enrollment'; 无法将值NULL插入列'IDStudent',表'HW32.dbo.Enrollment'; column does not allow nulls. 列不允许空值。 INSERT fails. INSERT失败。

when I insert values in the table Enrollment . 当我在表Enrollment插入值时。 Any help how to solve this? 有什么帮助怎么解决这个?

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

You don't want to INSERT a row in your trigger - the rows have already been added. 您不希望在触发器中插入行 - 已添加行。 Instead, you want to perform an 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

Things to note 注意事项

  • The above properly copes with inserted containing multiple rows 以上适当地处理了包含多行的inserted
  • I don't distinguish between father and mother (since they seem to be treated identically) 我不区分父亲和母亲(因为他们似乎被对待相同)
  • If there are multiple fathers and mothers associated with the student, they all get included. 如果有多个与学生有关的父亲和母亲,他们都被包括在内。 Whether this is right or not is debatable, and with better constraints may not be possible - but the original trigger doesn't cope with this situation at all well either. 这是否正确是值得商榷的,并且可能无法实现更好的约束 - 但原始触发器也无法应对这种情况。

As per my comment, I'd also recommend not storing this information if it can always be recalculated from the other tables (not sure if that's correct in this case, but if it should reflect the other tables, you'll needs lots more triggers to keep everything consistent. 根据我的评论,我还建议不要存储这些信息,如果它总是可以从其他表重新计算(在这种情况下不确定这是否正确,但如果它应该反映其他表,你将需要更多的触发器保持一致。

And as per-marc's deleted answer, it would also be a good habit to get into for you to always specify a column list when doing inserts. 并且根据per-marc的删除答案,在插入时总是指定列列表也是一个好习惯。 It's not the cause of this particular error, but helps to document your intentions better and helps to quickly eliminate possible errors by visual inspection. 这不是导致此特定错误的原因,但有助于更好地记录您的意图,并有助于通过目视检查快速消除可能的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM