我使用innodb引擎在触发表之前成功创建了一个插入,该引擎通过在不存在的表上执行插入来“抛出”错误。问题是,当我尝试在生产服务器上运行数据库创建脚本时,它会失败,因为插入表不存在。但是,同样的脚本在我的工作站上运行正常,这让我觉得有一个MySQL配置设置导致创建脚本失败。
我的问题提出的问题是生产服务器是在编译触发器而我的工作站是不是(或在运行时编译)。在生产环境中,我更希望在创建时编译SQL。
答案 0 :(得分:0)
我模拟在触发器中引发错误的方法是DECLARE
一个整数变量并在其中存储一个字符串。如果您有SQL_MODE = STRICT_ALL_TABLES
,则会引发错误。否则会引发警告。
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');
请注意,我将本地变量命名为与我要测试的列 bar 相同。这样,变量的名称出现在错误消息中,它与列相同:
ERROR 1366(HY000):不正确的整数值:'你不能存储那个值!'对于第1行的“bar”列
答案 1 :(得分:0)
事实证明表名的长度导致了问题。这两个服务器版本来自不同版本,服务器是先前版本(5.0 vs 5.1)。
至于在触发器中引发错误,我采取了不同的方法,但是根据MySQL处理create trigger语句的方式可能存在缺陷。如果在创建时验证了触发器语句,那么这将失败。
遇到错误(预期错误)后,我设置一个会话变量(变量名前缀为@),并显示错误消息。一旦设置了错误消息,我就插入到不存在的表Die中以引发MySQL中的错误。
然后,应用程序捕获数据库错误并对错误会话变量执行查询。根据结果我要么输出错误消息,数据库错误消息,要么让查询安静地失败,让调用代码处理失败的查询。
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);
}
}