gpt4 book ai didi

mysql - 如何将 MySQL 触发器异常/失败信息存储到表或变量中

转载 作者:搜寻专家 更新时间:2023-10-30 20:08:31 24 4
gpt4 key购买 nike

我被困在某个地方,需要你的帮助。

场景

我有两个数据库,即 test_db1test_db2 并且它们都有 users 表。两个数据库最初都是空的(0 行)。

这是 users 表架构:

DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` int(11) AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
`age` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

之后,我在 test_db1.users 上为 INSERTUPDATEDELETE 事件编写了一些触发器表,下面是每个触发器的作用:

  • test_db1.users 中的 INSERT 中,在 test_db2.users 中插入同一行
  • test_db1.users 中的 UPDATE 上,更新 test_db2.users 中的同一行
  • test_db1.users 中的 DELETE 上,从 test_db2.users 中删除同一行

这是触发代码片段。

DELIMITER //

-- TRIGGER FOR INSERT
DROP TRIGGER IF EXISTS `test_db1_users_bi`;
CREATE TRIGGER `test_db1_users_bi` BEFORE INSERT ON `users` FOR EACH ROW
BEGIN
INSERT INTO `test_db2`.`users` (id, name, age) VALUES (NEW.id, NEW.name, NEW.age);
END; //

-- TRIGGER FOR UPDATE
DROP TRIGGER IF EXISTS `test_db1_users_bu`;
CREATE TRIGGER `test_db1_users_bu` BEFORE UPDATE ON `users` FOR EACH ROW
BEGIN
UPDATE `test_db2`.`users`
SET name = NEW.name,
age = NEW.age
WHERE id = NEW.id;
END; //

-- TRIGGER FOR DELETE
DROP TRIGGER IF EXISTS `test_db1_users_bd`;
CREATE TRIGGER `test_db1_users_bd` BEFORE DELETE ON `users` FOR EACH ROW
BEGIN
DELETE FROM `test_db2`.`users`
WHERE id = OLD.id;
END; //

-- DELIMITER;

现在,问题!

目前,它没有在触发器中定义任何错误/异常处理程序。所以,我也想处理它,但我不知道该怎么做。我只是不知道如何获取异常及其属性,例如异常 - 错误代码、错误消息?

我只想将捕获的异常/错误存储到 test_db1errors 来自每个触发器的表(如果失败):

这是 errors 表架构,如下所示:

DROP TABLE IF EXISTS `errors`;
CREATE TABLE `errors` (
`id` int(11) AUTO_INCREMENT,
`error_code` varchar(30) DEFAULT NULL,
`error_message` TEXT DEFAULT NULL,
`emailed` TINYINT DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

仅供引用:以下是可能的故障:

  • 如果 test_db2 不存在或无法连接?
  • 如果 INSERT 触发器失败,即无论什么原因?
  • 如果 UPDATE 触发器失败,即无论什么原因?
  • 如果 DELETE 触发器失败,即无论什么原因?

如果有人可以告诉我如何获取异常及其属性(如错误代码、错误消息)并将其存储到触发器内部的变量中,以便我执行插入以将它们存储到表中?

我正在运行 MySQL 版本:5.5+

谢谢!

最佳答案

我通过 DECLARE CONTINUE HANDLERGET DIAGNOSTICS CONDITION 发现了一个 hack,所以我想,我必须在这里分享它。

这是我完整的最终脚本,它为两个数据库 users 表保持备份(同步)这意味着 test_db1 上的任何更新(我们可以称之为productionDB) 将发生在 test_db2 上(我们可以将其称为 stagingDB):

/*
Create two databases:
1. `test_db1`
2. `test_db2`
and execute below create *Table script* on both databases.
after that execute *Triggers Script* on `test_db1` only..
*/

/*
TABLE STRUCTURE FOR `users`
*/

DROP TABLE IF EXISTS `users`;
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) AUTO_INCREMENT NOT NULL,
`name` varchar(30) NOT NULL,
`age` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

/*
TABLE STRUCTURE FOR `errors`
*/

DROP TABLE IF EXISTS `errors`;
CREATE TABLE IF NOT EXISTS `errors` (
`id` int(11) AUTO_INCREMENT NOT NULL,
`code` varchar(30) NOT NULL,
`message` TEXT NOT NULL,
`query_type` varchar(50) NOT NULL,
`record_id` int(11) NOT NULL,
`on_db` varchar(50) NOT NULL,
`on_table` varchar(50) NOT NULL,
`emailed` TINYINT DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

/*
TRIGGERS SCRIPTS FOR INSERT, UPDATE AND DELETE OPERATIONS
*/

DELIMITER //

-- TRIGGER FOR INSERT
DROP TRIGGER IF EXISTS `test_db1_users_ai`;
CREATE TRIGGER `test_db1_users_ai` AFTER INSERT ON `users` FOR EACH ROW
BEGIN
-- Declare variables to hold diagnostics area information
DECLARE errorCode CHAR(5) DEFAULT '00000';
DECLARE errorMessage TEXT DEFAULT '';

-- Declare exception handler for failed insert
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
errorCode = RETURNED_SQLSTATE, errorMessage = MESSAGE_TEXT;
END;

-- Perform the insert
INSERT INTO `test_db2`.`users` (id, name, age) VALUES (NEW.id, NEW.name, NEW.age);

-- Check whether the insert was successful
IF errorCode != '00000' THEN
INSERT INTO `errors` (code, message, query_type, record_id, on_db, on_table) VALUES (errorCode, errorMessage, 'insert', NEW.id, 'test_db2', 'users');
END IF;
END; //

-- TRIGGER FOR UPDATE
DROP TRIGGER IF EXISTS `test_db1_users_au`;
CREATE TRIGGER `test_db1_users_au` AFTER UPDATE ON `users` FOR EACH ROW
BEGIN
-- Declare variables to hold diagnostics area information
DECLARE errorCode CHAR(5) DEFAULT '00000';
DECLARE errorMessage TEXT DEFAULT '';

-- Declare exception handler for failed insert
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
errorCode = RETURNED_SQLSTATE, errorMessage = MESSAGE_TEXT;
END;

-- Perform the update
UPDATE `test_db2`.`users`
SET name = NEW.name,
age = NEW.age
WHERE id = NEW.id;

-- Check whether the update was successful
IF errorCode != '00000' THEN
INSERT INTO `errors` (code, message, query_type, record_id, on_db, on_table) VALUES (errorCode, errorMessage, 'update', NEW.id, 'test_db2', 'users');
END IF;
END; //

-- TRIGGER FOR DELETE
DROP TRIGGER IF EXISTS `test_db1_users_ad`;
CREATE TRIGGER `test_db1_users_ad` AFTER DELETE ON `users` FOR EACH ROW
BEGIN
-- Declare variables to hold diagnostics area information
DECLARE errorCode CHAR(5) DEFAULT '00000';
DECLARE errorMessage TEXT DEFAULT '';

-- Declare exception handler for failed insert
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
errorCode = RETURNED_SQLSTATE, errorMessage = MESSAGE_TEXT;
END;

-- Perform the delete
DELETE FROM `test_db2`.`users`
WHERE id = OLD.id;

-- Check whether the insert was successful
IF errorCode != '00000' THEN
INSERT INTO `errors` (code, message, query_type, record_id, on_db, on_table) VALUES (errorCode, errorMessage, 'delete', OLD.id, 'test_db2', 'users');
END IF;
END; //

-- DELIMITER;

希望这会帮助到这里的其他人。

干杯,

关于mysql - 如何将 MySQL 触发器异常/失败信息存储到表或变量中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37680461/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com