触发函数来检查学生是不是有课

Posted

技术标签:

【中文标题】触发函数来检查学生是不是有课【英文标题】:Trigger function to check if student has classess触发函数来检查学生是否有课 【发布时间】:2017-01-06 01:59:56 【问题描述】:

我正在 Postgres 中创建一个数据库,用于为学生注册课程。

我一直在创建函数来检查想要注册课程的学生是否在他之前注册的那段时间没有任何其他课程。

有6张桌子:

CREATE TABLE "semester" (
    "semester_id" serial primary key,
    "semester_describtion" varchar);

CREATE TABLE "course" (
    "c_id" serial not null,
    "c_name" varchar NOT NULL,
    "c_describtion" varchar,
    "semester_id" int,
    "startDate" DATE,
    "endDate" DATE,
    PRIMARY KEY (c_id, semester_id),
    FOREIGN KEY (semester_id) references semester(semester_id));

CREATE TABLE "staff" (
    "staff_id" serial primary key,
    "staff_lastname" varchar(40) NOT NULL,
    "staff_firstname" varchar(40) NOT NULL,
    "staff_email" varchar(40));

CREATE TABLE "student" (
    "s_id" serial PRIMARY KEY,
    "s_lastname" varchar(40) NOT NULL,
    "s_firstname" varchar(40) NOT NULL,
    "semester_id" int default '1',
    foreign key (semester_id) references semester(semester_id));

CREATE TABLE "location" (
    "location_id" serial,
    "room_nr" int,
    "building_id" varchar(40) DEFAULT 'D5',
    "max_students" int default '10',
    primary key (location_id, max_students));

CREATE TABLE "course_section" (
    "c_section_id" serial,
    "c_id" int NOT NULL,
    "semester_id" int NOT NULL,
    "staff_id" int,
    "location_id" int not null,
    "c_section_date" DATE,
    "c_section_time" TIME default '08:00',
    "c_section_during" TIME default '01:30',
    "c_section_type" TEXT not null,
    "max_students" int default '10',
    "students" int default '0',
    check(c_section_type = 'L' OR c_section_type = 'W'
       OR c_section_type = 'C' OR c_section_type = 'I'),
    primary key (c_id, staff_id, location_id,c_section_date,c_section_time),
    foreign key (c_id, semester_id) references course(c_id, semester_id),
    foreign key (staff_id) references staff(staff_id),
    foreign key (location_id, max_students) references location(location_id, max_students)
    );

CREATE TABLE "enrollment" (
    "s_id" int not null,
    "mark" int,
    "c_id" int not null,
    "semester_id" int not null,
    primary key (s_id,c_id,semester_id),
    foreign key (s_id) references student(s_id),
    foreign key (c_id, semester_id) references course(c_id, semester_id));

触发函数和触发器:

create function check_date() returns trigger as '
declare
date1 date;
time1 time;
begin

Select c_section_date, c_section_time into date1, time1 from enrollment e 
inner join course c using (c_id)
inner join course_section cs using (c_id);

IF EXISTS  (select e.s_id , cs.c_section_date, cs.c_section_time from enrollment e 
inner join course c using (c_id)
inner join course_section cs using (c_id)
where new.s_id=e.s_id AND date1=c_section_date and time1 = c_section_time) THEN
RAISE NOTICE  ''You have classess on that time'';
Return null;
ELSE
return new;
END IF;
END;
' language 'plpgsql';

create trigger t_check_date before insert on enrollment for each row execute procedure check_date();

问题是它只能招收一个班级的学生。当我想插入enrollment 进行第二门课程时,它会显示RAISE NOTICE,尽管时间不同。

【问题讨论】:

您在函数中的第一个SELECT 没有WHERE 子句,这似乎没有任何意义。 【参考方案1】:

你的函数会这样工作:

CREATE OR REPLACE FUNCTION check_date() 
  RETURNS trigger AS
$func$
BEGIN
   IF EXISTS (
      SELECT 1
      FROM   course_section cs1
      WHERE  cs1.c_id        = NEW.c_id
      AND    cs1.semester_id = NEW.semester_id
      AND EXISTS (
         SELECT 1
         FROM   enrollment e 
         JOIN   course_section cs USING (c_id, semester_id)
         WHERE  e.semester_id      = NEW.semester_id
         AND    e.s_id             = NEW.s_id
         AND    cs.c_section_date  = cs1.c_section_date
         AND    cs.c_section_time  = cs1.c_section_time))  THEN

      RAISE NOTICE 'You have classes at that time';
      RETURN null;
   END IF;

   RETURN NEW;
END
$func$  LANGUAGE plpgsql;

表格course 只是我们可以省略的垫脚石。 enrollmentcourse_section 可以直接加入(c_id, semester_id)

但您确实应该检查的不仅仅是日期时间。您应该检查课程的重叠时间范围。

【讨论】:

感谢您的调查,但事实证明您的功能与我的功能相同。我的意思是我有同样的问题,它使我只能在一门课程中插入一名学生。我已在招生表中添加了时间和日期,并为每个 course_section 招收学生。这与我想要实现的目标相去甚远,但它现在有效

以上是关于触发函数来检查学生是不是有课的主要内容,如果未能解决你的问题,请参考以下文章

如何编写一个触发器来检查一个值是不是已经在表中?

Vue JS - 在触发函数之前检查数组中的所有项目是不是都已加载

如何编写触发器来检查工资是不是超出工资的最小或最大范围pl-sql Oracle

如何检查触发器是不是无效?

检查 SQL Server 中是不是存在触发器的最便携方法是啥?

数据库触发器问题