监视某个表的增删改查:触发器

触发器

触发器主要用于监视某个表的insert、update以及delete等更新操作,这些操作可以分别激活该表的insert、update或者delete类型的触发程序运行,从而实现数据的自动维护。
在这里插入图片描述
触发程序是与表有关的命名数据库对象,当表发生事件时,激活触发程序对象。如果定义了触发程序,一旦数据库执行事件语句时就会激发触发器执行相应的操作。

触发器是特殊的存储过程,都是嵌入到MySQL的一段程序。触发器由插入、更新和删除事件来触发某个操作。MySQL的触发事件有三种:

insert:将新记录插入表时激活触发程序,通过insert、load data和replace语句,可以激活触发程序运行。
update:更改某一行记录时激活触发程序,例如通过update语句,可以激活触发程序运行。
delete:从表中删除某一行记录时激活触发程序,通过delete和replace语句,可以激活触发程序运行。

创建触发器

创建一个或多个执行语句的触发器,语法如下:

CREATE  TRIGGER  名称  触发时机(before/after) 触发事件(INSERT/UPDATE/DELETEON 表名 FOR EACH ROW 触发程序体

before表示在触发事件发生之前执行触发程序;after表示在触发事件发生之后执行触发器;for each row表示更新(insert、update或者delete)操作影响的每一条记录都会执行一次触发程序。

CREATE TRIGGER tr_sum  AFTER  DELETE ON fruit  FOR  EACH  ROW  BEGIN 
		SET  @sum = @sum+NEW.f_price;
END//

【例5】创建一个包含多个执行语句的触发器

CREATE TABLE test1(a1 INT);
CREATE TABLE test2(a2 INT);
CREATE TABLE test3(a3 INT NOT NULL AUTO_INCREMENT PRIMARY KEY);
CREATE TABLE test4(
  a4 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
  b4 INT DEFAULT 0
);
/*创建触发器*/
DELIMITER //
CREATE TRIGGER testref BEFORE INSERT ON test1
  FOR EACH ROW BEGIN
    INSERT INTO test2 SET a2 = NEW.a1;
    DELETE FROM test3 WHERE a3 = NEW.a1;  
    UPDATE test4 SET b4 = b4 + 1 WHERE a4 = NEW.a1;
  END //

查看触发器

SHOW TRIGGERS语句查看触发器信息

通过SHOW TRIGGERS \G查看触发器,适合触发器较少的情况。
在triggers表中查看触发器信息

所有触发器的定义都在INFORMATION_SCHEMA数据库的TRIGGERS表格中,可以通过查询命令SELECT来查看。

SELECT * FROM INFORMATION_SCHEMA.TRIGGERS
	WHERE TRIGGER_NAME = ‘触发器名称’\G;

删除触发器

使用DROP TRIGGER语句可以删除MySQL中已经定义的触发器,语法如下:

DROP TRIGGER 数据库名 触发器名;

使用触发器的10条注意事项:

1.触发程序中如果包含select语句,该select语句不能返回结果集。

2.同一个表不能创建两个相同触发时间、触发事件的触发程序。

3.触发程序中不能使用以显式或隐式方式打开、开始或结束事务的语句,如start transaction、commit、rollback或者set autocommit=0等语句。

4.MySQL触发器针对记录进行操作,当批量更新数据时,引入触发器会导致更新操作性能降低。

5.在MyISAM存储引擎中,触发器不能保证原子性。InnoDB存储引擎支持事务,使用触发器可以保证更新操作与触发程序的原子性,此时触发程序和更新操作是在同一个事务中完成。

6.InnoDB存储引擎实现外键约束关系时,建议使用级联选项维护外键数据;MyISAM存储引擎虽然不支持外键约束关系时,但可以使用触发器实现级联修改和级联删除,进而维护“外键”数据,模拟实现外键约束关系。

7.使用触发器维护InnoDB外键约束的级联选项时,数据库开发人员究竟应该选择after触发器还是before触发器?答案是:应该首先维护子表的数据,然后再维护父表的数据,否则可能出现错误。

8.MySQL的触发程序不能对本表进行更新语句(例如update语句)。触发程序中的更新操作可以直接使用set命令替代,否则可能出现错误信息,甚至陷入死循环。

9.在before触发程序中,auto_increment字段的new值为0,不是实际插入新记录时自动生成的自增型字段值。

10.添加触发器后,建议对其进行详细的测试,测试通过后再决定是否使用触发器。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,下面是一个示例代码,可以创建这些并建立连接,并实现增删改查以及触发器: ```java // 导入所需的包 import java.sql.*; public class CreateTable { public static void main(String[] args) throws Exception { // 数据库连接信息 String url = "jdbc:mysql://localhost:3306/mydatabase"; String username = "root"; String password = "root"; // 建立连接 Connection conn = DriverManager.getConnection(url, username, password); // 创建用户 String sql1 = "CREATE TABLE users (" + "id INT NOT NULL AUTO_INCREMENT," + "username VARCHAR(50) NOT NULL," + "password VARCHAR(50) NOT NULL," + "PRIMARY KEY (id)" + ")"; PreparedStatement stmt1 = conn.prepareStatement(sql1); stmt1.executeUpdate(); // 创建价格 String sql2 = "CREATE TABLE prices (" + "id INT NOT NULL AUTO_INCREMENT," + "name VARCHAR(50) NOT NULL," + "price DECIMAL(10,2) NOT NULL," + "PRIMARY KEY (id)" + ")"; PreparedStatement stmt2 = conn.prepareStatement(sql2); stmt2.executeUpdate(); // 创建订单 String sql3 = "CREATE TABLE orders (" + "id INT NOT NULL AUTO_INCREMENT," + "user_id INT NOT NULL," + "price_id INT NOT NULL," + "order_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP," + "PRIMARY KEY (id)," + "FOREIGN KEY (user_id) REFERENCES users(id)," + "FOREIGN KEY (price_id) REFERENCES prices(id)" + ")"; PreparedStatement stmt3 = conn.prepareStatement(sql3); stmt3.executeUpdate(); // 创建管理员 String sql4 = "CREATE TABLE admins (" + "id INT NOT NULL AUTO_INCREMENT," + "username VARCHAR(50) NOT NULL," + "password VARCHAR(50) NOT NULL," + "PRIMARY KEY (id)" + ")"; PreparedStatement stmt4 = conn.prepareStatement(sql4); stmt4.executeUpdate(); // 创建触发器实现订单插入数据时更新用户的余额信息 String sql5 = "CREATE TRIGGER update_user_balance AFTER INSERT ON orders FOR EACH ROW " + "UPDATE users SET balance = balance - (SELECT price FROM prices WHERE id = NEW.price_id) " + "WHERE id = NEW.user_id"; PreparedStatement stmt5 = conn.prepareStatement(sql5); stmt5.executeUpdate(); // 插入一些示例数据 String sql6 = "INSERT INTO users (username, password) VALUES ('user1', 'password1')"; PreparedStatement stmt6 = conn.prepareStatement(sql6); stmt6.executeUpdate(); String sql7 = "INSERT INTO prices (name, price) VALUES ('product1', 10.00)"; PreparedStatement stmt7 = conn.prepareStatement(sql7); stmt7.executeUpdate(); String sql8 = "INSERT INTO orders (user_id, price_id) VALUES (1, 1)"; PreparedStatement stmt8 = conn.prepareStatement(sql8); stmt8.executeUpdate(); // 查询示例数据 String sql9 = "SELECT * FROM users"; PreparedStatement stmt9 = conn.prepareStatement(sql9); ResultSet rs1 = stmt9.executeQuery(); while (rs1.next()) { System.out.println("id: " + rs1.getInt("id") + ", username: " + rs1.getString("username") + ", password: " + rs1.getString("password")); } String sql10 = "SELECT * FROM prices"; PreparedStatement stmt10 = conn.prepareStatement(sql10); ResultSet rs2 = stmt10.executeQuery(); while (rs2.next()) { System.out.println("id: " + rs2.getInt("id") + ", name: " + rs2.getString("name") + ", price: " + rs2.getDouble("price")); } String sql11 = "SELECT * FROM orders"; PreparedStatement stmt11 = conn.prepareStatement(sql11); ResultSet rs3 = stmt11.executeQuery(); while (rs3.next()) { System.out.println("id: " + rs3.getInt("id") + ", user_id: " + rs3.getInt("user_id") + ", price_id: " + rs3.getInt("price_id") + ", order_time: " + rs3.getTimestamp("order_time")); } // 更新示例数据 String sql12 = "UPDATE users SET password = 'newpassword' WHERE id = 1"; PreparedStatement stmt12 = conn.prepareStatement(sql12); stmt12.executeUpdate(); // 删除示例数据 String sql13 = "DELETE FROM orders WHERE id = 1"; PreparedStatement stmt13 = conn.prepareStatement(sql13); stmt13.executeUpdate(); // 关闭连接 conn.close(); } } ``` 这段代码可以创建四个,并且实现增删改查以及一个触发器,当订单插入数据时自动更新用户的余额信息。 希望这能对您有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿珊和她的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值