仅显示Firebird异常消息

时间:2013-03-26 01:58:17

标签: delphi stored-procedures firebird unidac

我有一个从更新前触发器调用的存储过程。在这个过程中,我检查一些条件,如果遇到异常被抛出

异常显示许多我不想向用户显示的数据的问题:

  例外4
      Exception_Name
      错误消息在过程'proc_name'行:3,col:50
      在触发器'trigger_name'行:8,col:17。

有没有办法只显示消息?如果没有,有没有办法停止更新而不抛出异常?

我正在使用Firebird 2.5.1和Delphi 2010 数据库连接:从post方法

触发IBDac和更新

2 个答案:

答案 0 :(得分:1)

有点迟到的回答,但总比没有好。

这是我的解决方案。不太好或不专业,有点黑客,但我没有找到更好的选择。

我在 IB.pas 文件(IBX)中修改了以下程序,运行正常。我知道OP使用不同的包访问数据库,但我猜逻辑将是相同的。

procedure IBDataBaseError;
var
  sqlcode: Long;
  IBErrorCode: Long;
  local_buffer: array[0..IBHugeLocalBufferLength - 1] of char;
  usr_msg: string;
  status_vector: PISC_STATUS;
  IBDataBaseErrorMessages: TIBDataBaseErrorMessages;
  AStrList: TStringList;
  i: integer;
begin
  usr_msg := '';

  { Get a local reference to the status vector.
    Get a local copy of the IBDataBaseErrorMessages options.
    Get the SQL error code }
  status_vector := StatusVector;
  IBErrorCode := StatusVectorArray[1];
  IBDataBaseErrorMessages := GetIBDataBaseErrorMessages;
  sqlcode := GetGDSLibrary.isc_sqlcode(status_vector);

  if (ShowSQLCode in IBDataBaseErrorMessages) then
    usr_msg := usr_msg + 'SQLCODE: ' + IntToStr(sqlcode); {do not localize}
  Exclude(IBDataBaseErrorMessages, ShowSQLMessage);
  if (ShowSQLMessage in IBDataBaseErrorMessages) then
  begin
    GetGDSLibrary.isc_sql_interprete(sqlcode, local_buffer, IBLocalBufferLength);
    if (ShowSQLCode in IBDataBaseErrorMessages) then
      usr_msg := usr_msg + CRLF;
    usr_msg := usr_msg + string(local_buffer);
  end;

  if (ShowIBMessage in IBDataBaseErrorMessages) then
  begin
// unnecessary code
//    if (ShowSQLCode in IBDataBaseErrorMessages) or
//       (ShowSQLMessage in IBDataBaseErrorMessages) then
//      usr_msg := usr_msg + CRLF;
    while (GetGDSLibrary.isc_interprete(local_buffer, @status_vector) > 0) do
    begin
      if (usr_msg <> '') and (usr_msg[Length(usr_msg)] <> LF) then
        usr_msg := usr_msg + CRLF;
      usr_msg := usr_msg + string(local_buffer);
    end;

    // then next condition is optional, remove if you use other 
    // initialization than SetIBDataBaseErrorMessages([ShowIBMessage])
    if (IBDataBaseErrorMessages = [ShowIBMessage]) then
    begin
      AStrList:= TStringList.Create;
      try
        AStrList.Text:= usr_msg;
        // apply to user defined exception only
        if (AStrList.Count > 0) and (Pos('exception', AStrList[0]) = 1) then
          // i'm using ! on the end of every exception
          // if you don't, just simply keep the 3. line (AStrList[2])
          // of AStrList and delete the rest of lines 
          for i:= AStrList.Count - 1 downto 0 do
            if (Pos('!', AStrList[i]) = 0) then
              AStrList.Delete(i);
        usr_msg:= AStrList.Text;
      finally
        AStrList.Free;
      end;
    end;
  end;

  while (usr_msg <> '') and ((usr_msg[Length(usr_msg)] = '.') or (usr_msg[Length(usr_msg)] = LF) or (usr_msg[Length(usr_msg)] = CR)) do
    Delete(usr_msg, Length(usr_msg), 1);
  MonitorHook.SendError(IntToStr(sqlcode) + ' ' + IntToStr(IBErrorCode) + ' ' + usr_msg);
  if sqlcode <> -551 then
    raise EIBInterBaseError.Create(sqlcode, IBErrorCode, usr_msg)
  else
    raise EIBInterBaseRoleError.Create(sqlcode, IBErrorCode, usr_msg)
end;

答案 1 :(得分:0)

异常最有可能包含错误的每个部分的属性。您可能会查看异常类的声明(您在问题中没有提到)。例如,EDatabaseError具有ErrorCodeErrorMessage的属性;我怀疑FireBird错误也有它们。

这意味着您的异常处理程序可以执行以下操作:

try
  .. some database thing
except
  on E: EFireBirdException do
    ShowMessage(E.ErrorMessage);
end;

请注意,我不知道FireBird异常类提供了什么;我只是在Firebird异常类声明中提供您应该寻找的类型。其他有用的值通常是ErrorCode

再次,看看可以使用的是异常类声明和异常类的特定功能(如E.Message,E.Code等等,你需要查看特定的类,你需要处理。