MySQL创建“插入前”触发器失败并在触发器中引发错误
我已经使用innodb引擎成功地在一个表上创建了一个insert before触发器,它通过在一个不存在的表上执行insert来抛出一个错误。问题是,当我尝试在生产服务器上运行数据库创建脚本时,它失败了,因为插入表不存在。然而,同样的脚本在我的工作站上运行良好,这让我认为有一个MySQL配置设置导致创建脚本失败MySQL创建“插入前”触发器失败并在触发器中引发错误,mysql,sql,error-handling,triggers,raiseevent,Mysql,Sql,Error Handling,Triggers,Raiseevent,我已经使用innodb引擎成功地在一个表上创建了一个insert before触发器,它通过在一个不存在的表上执行insert来抛出一个错误。问题是,当我尝试在生产服务器上运行数据库创建脚本时,它失败了,因为插入表不存在。然而,同样的脚本在我的工作站上运行良好,这让我认为有一个MySQL配置设置导致创建脚本失败 我提出的问题是,生产服务器是否正在编译触发器,而我的工作站是否正在编译或在运行时编译。在生产环境中,我更希望在创建SQL时对其进行编译 我模拟在触发器中引发错误的方法是声明一个整数变量并
我提出的问题是,生产服务器是否正在编译触发器,而我的工作站是否正在编译或在运行时编译。在生产环境中,我更希望在创建SQL时对其进行编译 我模拟在触发器中引发错误的方法是声明一个整数变量并在其中存储一个字符串。如果您有SQL\u MODE=STRICT\u ALL\u表,则会引发错误。否则会引起警告
use test;
drop table if exists foo;
create table foo (id serial primary key, bar varchar(10));
drop trigger if exists RaiseError;
delimiter //
create trigger RaiseError before insert on foo
for each row
begin
declare bar int;
if new.bar = 'boom' then
set bar = 'You cannot store that value!';
end if;
end //
delimiter ;
set sql_mode = strict_all_tables;
insert into foo (bar) values ('boom');
请注意,我将局部变量命名为与要测试的列栏相同的名称。这样,变量的名称就会出现在错误消息中,它与列相同:
错误1366 HY000:整数值不正确:“无法存储该值!”对于第1行的“bar”列
结果是表名的长度导致了问题。这两个服务器版本来自不同的版本,服务器是5.0和5.1的早期版本
至于在触发器中引发错误,我采取了一种不同的方法,但是根据MySQL处理CREATETRIGGER语句的方式,这种方法可能有缺陷。如果触发器语句在创建时得到验证,则此操作将失败
一旦遇到错误,我将设置一个以@为前缀的会话变量名,并显示错误消息。一旦设置了错误消息,我就在不存在的表中插入一个Die,以在MySQL中引发一个错误
然后应用程序捕获数据库错误并对error会话变量执行查询。根据结果,我要么抛出带有错误消息的异常,要么抛出数据库错误消息,要么让查询安静地失败,留下调用代码来处理失败的查询
MySQL触发器:
CREATE TRIGGER Error_Trigger
BEFORE INSERT ON Fubar
FOR EACH ROW
BEGIN
if DataIsBad then
set @Err = 'The data is fubared.';
insert into Die values (1);
end if;
END$$
应用程序端代码:
public function getDatabaseErrorMessage($AdminMessage = false){
if ($this->db->_error_number() != 0){
$AdminError = $this->db->_error_message();
$Query = $this->db->query("select @Err");
if ($Query){
$Error = $Query->row_array();
}
if (isset($Error["@Err"]) && $Error["@Err"] != ""){
$Error = $Error["@Err"];
$this->db->query("set @Err = ''");
} else {
if ($AdminMessage){
$Error = $AdminError;
} else {
return false;
}
}
throw new Exception($Error);
}
}