数据库实验四:触发器实验

实验四 触发器实验

1.实验目的

​ 掌握数据库触发器的设计和使用方法。

2.实验内容和要求

​ 定义BEFORE触发器和AFTER触发器,能够理解不同类型触发器的作用和执行原理,验证触发器的有效性。

3.实验重点和难点

​ 实验重点:触发器的定义。

​ 实验难点:利用触发器实现较为复杂的用户自定义完整性。

4.实验过程

​ 创建一个教材信息表,教材订购表,开支表,一个选课统计表用于实验。

/*教材信息表*/
CREATE TABLE textbook(
	bookno CHAR(10) PRIMARY KEY,
    bookname CHAR(20),
    cno char(9) REFERENCES Course(Cno),
    price SMALLINT,								/*单价*/
    discount_quantity SMALLINT,					/*折扣数量,超过该数量的订单可以使用折扣价格*/
    discount FLOAT								/*折扣*/
);
/*教材订购表*/
CREATE TABLE textbook_order(
	order_idx CHAR(10) PRIMARY KEY,			
    bookno CHAR(10),
    num SMALLINT,								/*订购数量*/
    total_price SMALLINT,						/*总价*/
    order_status CHAR(10)	DEFAULT "未确认",    /*订单状态*/
    CHECK(order_status IN ("未确认","已确认"))
);
/*开支表*/
CREATE TABLE expenditure(
    expenditure_type CHAR(20),
    amount INT,
    creater_no CHAR(10),
    order_status CHAR(20)
);
/*选课统计表*/
CREATE TABLE sc_summary(
	Cno char(9),
	cyear YEAR,
    term CHAR(2),
    snum SMALLINT,								/*已选人数*/
    capacity SMALLINT,							/*课程容量*/
    PRIMARY KEY(cno,cyear,term)
);

(1)AFTER触发器

​ 在textbook表上定义一个UPDATE触发器,当修改教材价格,折扣数量,折扣时,修改教材订购表。在教材订购表上定义一个UPDATE触发器,修改教材订购表后修改开支表,保持数据一致性。

/*修改教材订购表的触发器*/
DELIMITER $
CREATE TRIGGER after_textbook_update
AFTER UPDATE ON textbook
FOR EACH ROW
BEGIN
	/*如果编号发生了修改,订购表中的教材编号也要修改*/
	UPDATE textbook_order
    SET bookno = new.bookno
    WHERE bookno = old.bookno;
    /*计算正确的订单价格*/
	UPDATE textbook_order
	SET total_price = num*new.discount*new.price
	WHERE bookno=new.bookno AND new.discount_quantity<=num;
	UPDATE textbook_order
	SET total_price = num*new.price
	WHERE bookno=new.bookno AND new.discount_quantity>num;
END$
DELIMITER ;
/*修改开支表的触发器*/
DELIMITER $
CREATE TRIGGER after_textbook_order_update
AFTER UPDATE ON textbook_order
FOR EACH ROW
BEGIN
	UPDATE expenditure
	SET amount = amount-old.total_price+new.total_price
	WHERE expenditure_type = "textbook";
END$
DELIMITER ;

​ 在教材订购表上添加一个INSERT触发器,当增加一个教材订购订单表时,修改开支表中教材开支的费用,以保持数据的一致性。

DELIMITER $
CREATE TRIGGER after_insert_textbook_order
AFTER INSERT ON textbook_order
FOR EACH ROW
BEGIN
	UPDATE expenditure
    SET amount = amount+new.total_price
    WHERE expenditure_type="textbook";
END$
DELIMITER ;

​ 在教材订购表上添加一个DELETE触发器,当教材订购表删除一个订单时,删除开支中的费用,保持数据的一致性。

DELIMITER $
CREATE TRIGGER after_delete_textbook_order
AFTER DELETE ON textbook_order
FOR EACH ROW
BEGIN
	UPDATE expenditure
    SET amount = amount-old.total_price
    WHERE expenditure_type = "textbook";
END$
DELIMITER ;

​ 验证after_textbook_update,修改一本书的折扣。

/*插入一本教材和相应订单*/
INSERT INTO textbook
VALUES("2105","5",30,150,0.85,"数据库原理");
INSERT INTO textbook_order
VALUES("1","2105","200",5100,"未确认");
select * from textbook_order;

在这里插入图片描述

/*修改折扣*/
SET SQL_SAFE_UPDATES = 0;
UPDATE textbook
SET discount=0.82
WHERE bookno="2105";
SELECT * FROM textbook_order;
SELECT * FROM expenditure;

在这里插入图片描述

在这里插入图片描述

​ 修改折扣后,教材订购表中的总金额重新进行了计算,开支表中的数据也相应修改。

(2)BEFORE触发器

​ 在教材订购表上定义一个BEFORE UPDATE触发器,当修改订单时,如果订单的状态是"已确认",则拒绝修改。

DELIMITER $
CREATE TRIGGER before_update_textbook_order
BEFORE UPDATE ON textbook_order
FOR EACH ROW
BEGIN
	IF(old.order_status="已确认") THEN
		SIGNAL SQLSTATE 'TX000' SET MESSAGE_TEXT = '该订单已确认,不可修改';
	END IF;
END$
DELIMITER ;

​ 在选课表上定义一个INSERT触发器,当插入一条选课记录时,先查询选课统计表中是否还有剩余的选课容量,有剩余的容量才可以插入该选课记录,并更新选课统计表中的值。

DELIMITER $
CREATE TRIGGER before_insert_sc
BEFORE INSERT ON sc
FOR EACH ROW
BEGIN
	DECLARE available_capacity SMALLINT;
	SELECT capacity-snum INTO available_capacity
	FROM sc_summary;
	IF(available_capacity>0) THEN
		UPDATE sc_summary
		SET snum = snum + 1
		where cno = new.cno;
	ELSE 
		SIGNAL SQLSTATE 'TX000' SET MESSAGE_TEXT = '该课程已无剩余容量!';
	END IF;
END$
DELIMITER ;

​ 在选课表上定义一个DELETE触发器,当删除一个选课记录时,将相应的选课统计表中的选课人数-1。

DELIMITER $
CREATE TRIGGER before_delete_sc
BEFORE DELETE ON sc
FOR EACH ROW
BEGIN
	UPDATE sc_summary
	SET snum = snum-1
	WHERE cno = old.cno;
END$
DELIMITER ;

​ 验证before_update_text_book触发器,修改状态为"已确认"的订单。

/*将订单1修改为已确认*/
UPDATE textbook_order
SET order_status="已确认"
WHERE order_idx="1";
/*修改该订单*/
UPDATE textbook_order
SET num=300
WHERE order_idx="1";

在这里插入图片描述

​ 验证before_insert_sc触发器,对一个无容量的课程插入选课记录。

/*插入一个课程,容量为0*/
INSERT INTO sc_summary
VALUES("5","2022","1",0,0);
/*插入一个选课记录*/
INSERT INTO sc
VALUES("202004152","5",NULL);

在这里插入图片描述

(3)删除触发器

​ 删除触发器after_textbook_update。

DROP TRIGGER after_textbook_update;

5.实验总结

​ 触发器类似于约束,但能实现更复杂的检查和操作,尤其是可以在动作体中对其他表或数据库对象进行修改。使用BEFORE触发器在MYSQL中可以通过SIGNAL语句抛出异常,拒绝执行。

6.思考题

​ 设计一个AFTER触发器,当Lineitem表中的quantity变化时,自动计算Lineitem中的extendedprice值,同时也要修改PartSupp中的availqty值。

​ 实现如下:

DELIMITER $
CREATE TRIGGER after_update_lineitem
AFTER UPDATE lineitem
FOR EACH ROW
BEGIN
	DECLARE rp REAL;
	SELECT retailprice INTO rp
	FROM Part
	WHERE new.partkey = Part.partkey;
	/*重新计算extendedprice*/
	UPDATE lineitem
	SET extendedprice =  new.quantity*rp
    WHERE partkey = new.partkey AND suppkey=new.suppkey;
    /*更新PartSupp中的availqty*/
    UPDATE PartSupp
    SET availqty = availqty+old.quantity-new.quantity
    WHERE partkey = new.partkey AND suppkey=new.suppkey;
END$
DELIMITER ;
  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验5.1 存储过程的建立与使用 一、实验目的 理解存储过程的概念、作用、建立和调用方法。 二、实验原理 使用CREATE PROCEDURE语句创建存储过程,ALTER PROCEDURE语句修改存储过程,DROP PROCEDURE语句删除存储过程,存储过程有不带参数的、有带输入参数的、有带输出参数(output)的,还可以有带返回值的。创建好的存储过程可以使用EXEC procedure_name语句执行。 实验5.2 触发器的建立与使用 一、实验目的 理解触发器的概念和作用;了解触发器的分类及触发条件;掌握触发器的定义及应用。 二、实验原理 1、 使用CREATE TRIGGER语句定义触发器,ALTER TRIGGER语句修改触发器,DROP TRIGGER语句删除触发器。 2、 触发器分AFTER/FOR和INSTEAD OF两种类型:AFTER/FOR类型的触发器是在相应的触发语句(insert、delete、update)执行完后被触发的。如果触发语句对应的表上有完整性约束,这些完整性约束必须不违背时,相应的触发语句才能执行,然后才能触发对应的AFTER/FOR类型的触发器。INSTEAD OF类型的触发器会在触发语句(insert、delete、update)执行之前被触发,并取代相应的触发语句。 3、 在表或视图上,每个INSERT、UPDATE或DELETE语句只能创建一个INSTEAD OF类型的触发器,无法为有外键约束且指定为级联删除或级联修改的表创建DELETE或UPDATE语句上的INSTEAD OF 类型的触发器。 SQL SERVER为每个触发器都创建了两个临时表INSERTED表和DELETED表,这两个表的逻辑结构与被触发器作用的表一样,用户可以读取这两个表的内容,但不能对它们进行修改,触发器执行完后,这两个表也会自动删除。当执行INSERT时,INSERTED表中保存要向表中插入的所有行;当执行DELETE时,DELETED表中保存要从表中删除的所有行;当执行UPDATE时,修改前的行保存在DELETED表中,修改后的行保存在INSERTED行中。
好的,以下是一个简单的数据库实验触发器实验: 1. 创建一个数据库表,包含以下字段:id(自增主键)、name、age、gender。 2. 编写一个触发器,当插入一条记录时,自动为该记录生成一个唯一的ID。触发器可以使用MySQL的内置函数UUID()生成。 3. 编写一个触发器,当删除一条记录时,自动将该记录的信息写入另一张日志表中,包括被删除记录的ID、姓名、年龄和性别。 4. 编写一个触发器,当更新一条记录时,自动将该记录的信息写入另一张历史表中,包括被更新记录的ID、姓名、年龄和性别。历史表应该具有时间戳字段,以便记录更新的时间。 下面是具体的实现步骤: 1. 创建一个名为“person”的表: ``` CREATE TABLE person ( id INT(11) NOT NULL AUTO_INCREMENT, name VARCHAR(50) NOT NULL, age INT(11) NOT NULL, gender enum('M', 'F') NOT NULL, PRIMARY KEY (id) ); ``` 2. 创建一个名为“person_uuid”的触发器,用于自动生成ID: ``` CREATE TRIGGER person_uuid BEFORE INSERT ON person FOR EACH ROW SET NEW.id = UUID(); ``` 3. 创建一个名为“person_log”的表,用于记录删除操作: ``` CREATE TABLE person_log ( id INT(11) NOT NULL, name VARCHAR(50) NOT NULL, age INT(11) NOT NULL, gender enum('M', 'F') NOT NULL, deleted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); ``` 4. 创建一个名为“person_delete”的触发器,用于将删除操作记录到日志表中: ``` CREATE TRIGGER person_delete AFTER DELETE ON person FOR EACH ROW INSERT INTO person_log (id, name, age, gender) VALUES (OLD.id, OLD.name, OLD.age, OLD.gender); ``` 5. 创建一个名为“person_history”的表,用于记录更新操作: ``` CREATE TABLE person_history ( id INT(11) NOT NULL, name VARCHAR(50) NOT NULL, age INT(11) NOT NULL, gender enum('M', 'F') NOT NULL, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); ``` 6. 创建一个名为“person_update”的触发器,用于将更新操作记录到历史表中: ``` CREATE TRIGGER person_update AFTER UPDATE ON person FOR EACH ROW INSERT INTO person_history (id, name, age, gender) VALUES (OLD.id, OLD.name, OLD.age, OLD.gender); ``` 以上就是一个简单的数据库实验触发器实验。通过此实验,你可以了解如何使用MySQL触发器来自动生成唯一ID,记录删除操作和记录更新操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值