老板要我做一个通用的数据库出错处理程序,
处理如主键重复或未输入主键之类的数据库错误。
哪位朋友做过或对此有经验,请给个建议,
十分感谢。

解决方案 »

  1.   

    好吧,我把我知道的先说一下。
    如果数据库发生错误,会将所有的错误放在Connetion的Errors集合中。
    集合中每一个Error对象都有Number(ADO产生的错误号),NationError(数据库系统产生的错误号)属性.
      

  2.   

    unit MyErrorMessage;
    interface
    …..
    type
    TFrm_ErrorMessage = class(TForm)
    ……
    procedure MyErrorMessage(Sender:TObject;E: Exception);
    //定义代替OnException事件的句柄
    procedure FormCreate(Sender: TObject);
    private
    ……
    File_Name:String;//保存异常信息的文件名
    public
    end;
    var
    Frm_ErrorMessage: TFrm_ErrorMessage;
    implementation
    ……
    procedure TFrm_ErrorMessage.MyErrorMessage(Sender: TObject; E: Exception);
    var F: TextFile; //Text类型文件的句柄
    SaveMessage:String; //代保存的异常信息
    FrmHandle:Integer; //触发异常模块所在的窗口句柄
    Ls_Title:array[0..254] of Char; //触发异常模块所在的窗口的标题
    begin
    if e is EConvertError then //判断异常类型
    Label1.Caption:='输入的数据类型错误'
    else if e is EDatabaseError then
    Label1.Caption:='数据库错误'
    ……
    else
    Label1.Caption:='系统错误!' ;
    end;
    FrmHandle:=GetactiveWindow(); //获取触发异常模块所在的窗口句柄(活动窗口句柄)
    if FrmHandle<>Null then
    if GetWindowText(FrmHandle,Ls_Title,255)>0 then //获取异常模块所在的窗口的标题
    SaveMessage:= StrPas(Ls_Title) else SaveMessage:='无标题'; //记录窗口的标题
    Try // 把异常信息保存到数据库表(AppError)中,可能再次触发异常
    If Not QureyAppError.Active then QureyAppError.Active:=true;//打开数据集
    QureyAppError.AppendRecord([Label1.caption,StrPas(Ls_Title),Sender.ClassName,now,
    e.Message]); //把触发异常的类型,窗口标题、类名、时间、异常原因保存到数据库中
    QureyAppError.post;
    Except //如果触发错误,则把错误信息保存到文件中
    SaveMessage:=Label1.caption; //记录异常类型
    SaveMessage:=SaveMessage+' '+Sender.ClassName; //记录异常模块所在的类名
    SaveMessage:=SaveMessage+' '+FormatDateTime('yyyy-mm-dd hh:ss ',now);//时间
    SaveMessage:=SaveMessage+' '+e.Message; //记录异常原因
    Try //文件操作可能再次触发异常
    if not FileExists(File_Name) then
    FileClose(FileCreate(File_Name));//创建保存异常信息文件
    AssignFile(F,File_Name); //打开文件
    Append(F); //设置增加的模式
    Writeln(F, SaveMessage); //把异常信息追加到文件中
    CloseFile(F); //关闭文件
    Finally
    End;
    End;
    Frm_ErrorMessage.ShowModal; //显示提示窗口
    end;
    procedure TFrm_ErrorMessage.FormCreate(Sender: TObject);
    begin
    …….
    Application.OnException:=Frm_ErrorMessage.MyErrorMessage; //代替默认的异常处理句柄
    File_Name:=ExtractFilePath(Application.ExeName)+ChangeFileExt(ExtractFileName(Application.E xeName),'.txt'); //设置保存异常信息的文件名为应用程序文件名,但改变后缀为'.txt'
    end; end.
      

  3.   

    try
    adoconnection1.beginstran;
    do.....
    adoconnection.commitstran;
    except
    adoconnection1.rollbacktran;  //显示错误
    for I := 0 to adoconnection1.Errors.Count - 1 do
        begin
          case AParam.AConnection.Errors[I].NativeError of
            547  : begin
                     if pos('insert',AParam.AConnection.Errors[I].Description) > 0 then
                     begin
                       //'外键约束insert,delete,update';
                       if sErrText <> '' then sErrText := sErrText + #13;
                       sErrText := sErrText + 's';
                     end
                     else
                     if pos('delete',AParam.AConnection.Errors[I].Description) > 0 then
                     begin
                       if sErrText <> '' then sErrText := sErrText + #13;
                       sErrText := sErrText + 's';
                     end
                     else
                     if pos('update',AParam.AConnection.Errors[I].Description) > 0 then
                     begin
                       if sErrText <> '' then sErrText := sErrText + #13;
                       sErrText := sErrText + 's';
                     end;
                   end;//end of 547        945  : begin
                     if sErrText <> '' then sErrText := sErrText + #13;
                     sErrText := sErrText + '您的内存不足!';
                   end;//end of 945        4850 : begin
                     if sErrText <> '' then sErrText := sErrText + #13;
                     sErrText := sErrText + '数据库表被锁定!';
                   end;//end of 1204        2627 : begin
                     if sErrText <> '' then sErrText := sErrText + #13;
                     sErrText := sErrText + '输入的关键属性值已经存在!';
                   end;//end of 2627        7303 : begin
                     if sErrText <> '' then sErrText := sErrText + #13;
                     sErrText := sErrText + '网络初始化失败!请检查网络设置!';
                   end;//end of 7303        10024: begin
                     if sErrText <> '' then sErrText := sErrText + #13;
                     sErrText := sErrText + '网络连接超时!请检查网络设置!';
                   end;//end of 10024        else   begin
                     if
                   end;
          end;//end of case    end;//end of for
        //最后显示错误信息sErrText 
    end;
    ______________
    做个调查,关于软件界面
    http://expert.csdn.net/Expert/TopicView2.asp?id=1649010
    谢谢关注
      

  4.   

    to My_first(小@_@小)
    据我所知如果数据库发生一个错误,例如主键错误,得到的Errors.Count=2
    Errors[0].NationError的值为数据库系统提示的主键重复的错误号(对于SQLServer
    为2627),Errors[1].NationError好像是一个定值。
    另外,使用NationError的话,同一个错误(就拿主键重复来说)数据库系统不同的话,
    NationError的值也不同。我不知道使用Number属性是否可得到相同的错误号。请高手指点。
      

  5.   

    csouth(金子) 的方法是比较实际的,也是最常用的,包括了所有的错误处理都可以在其中。可以放到错误日值中去。
      

  6.   

    数据库出错后,数据库服务器会回传一个错误,包括错误号和错误信息,被dberror捕捉,你可以直接解释dberror就行了,而且已经有解释的了,只不过是鸟语英文的。在sql的master库中sysmessage表有全部的错误码解释。
      

  7.   

    实际上程序中的错误不光只有数据库系统的错误,还有ADO本身的错误。
    例如,ADO无法定位行之类的错误。
      

  8.   

    如果我想得到错误信息和错误号,在发生错误时,直接可以通过:
    AdoConnection.ConnectionObject.Errors[0].Desription和
    AdoConnection.ConnectionObject.Errors[0].Number
    来得到。
    EDatabaseError的Message属性也是来自上述的Desription属性。