用try ..except .当程序不处于调试态时,
操作数据库错误不会弹出提示框.
截获错误用 ON EXCEPTION
例如
with query1 do
begin
....
close ;
sql.clear ;
sql.add('insert into tb values(0,0)');
try
execute ;
except
....
on E: Exception do //截获错误
begin
ErrMessage := E.Message ;
if Pos('PRIMARY KEY',ErrMessage) <> 0 then
{如果是主键重复}
begin
ProcError(ERR_PRIMARYKEY) ;
end
else
begin
{如果其它错误}
ProcError(ERR_OTHERERROR) ;
end ;
end ;
end ;
用Delphi开发数据库系统时,一定会遇到与数据库配合的问题,最基本的一个问题就是怎样处理数据库约束(constraint)产生的错误。如果用户录入的数据违反约束,数据库会产生类似“Violation of PRIMARY KEY constraint 'PK__table1__07F6335A'. Cannot insert duplicate key in object 'table1'. The statement has been terminated.”这样含混的提示,而用户真正希望看到的是“商品已经存在,您输入的编号重复,请重新输入。”这样的提示,怎样才能把数据库的异常转换为用户可以理解的错误提示呢?这是一个非常常见的问题,但令人遗憾的是在用户手册和流行的参考资料中都找不到直接答案,所以很多开发人员使用了一些令人哭笑不得的办法。比如不创建主键(primary key),而是在每次插入数据之前先查询是否存在相同的数据。又比如不创建外键(foreign key),靠额外的查询来检查数据是否冲突。姑且不论这样做程序代码会有多么臃肿,仅从理论上就可以推论出这是违反并发控制原理的,在你查询和插入之间其它用户完全可能改变了数据库,也就是说用提前查询的办法来代替约束只解决99%的问题,而且随着并发用户的增加,这个百分比还会下降。因此,并发情况下只能依靠数据库约束检查数据,那么Delphi这边怎样做才能替换数据库的错误提示呢?
回到数据库的话题,程序插入重复数据时,在屏幕上出现“Violation of PRIMARY KEY ...”之前,VCL里面都发生了什么事呢?首先,在Post或者ExecSQL以后,VCL将调用BDE执行SQL,并取得数据库返回的结果代码。如果数据库发现新数据违反约束,会返回错误代码和错误提示,由于不同的数据库规定了不同的错误代码,VCL会针对数据库的类型把原始错误代码转换为BDE统一规定的代码,然后生成一个叫做EDBEngineError的异常,其中包括BDE错误代码、数据库原始错误代码和数据库错误提示。这个异常将中断Post/ExecSQL,如果Post/ExecSQL处于try...except保护之中,程序会跳到except部分寻找相应的处理分支。如果没有try...except或者except中没有对应的处理分支,异常会中断当前的过程/函数,跳回到上级调用者。如果各级程序都没有try...except,那么最终VCL会替你处理,弹出大家熟悉的错误对话框,里面显示数据库的原始错误提示。