【问题标题】:delphi has ExecSQL succeeded or faileddelphi 有 ExecSQL 成功还是失败
【发布时间】:2013-01-24 21:50:06
【问题描述】:

您好,我有这个功能可以使用 TUniQuery 更新我的 Access DB:

var
  Res:Boolean;
begin
Res:=false;
  try
  with MyQuery do
  begin
    Active := false;
    SQL.Clear;
    SQL.Add('Update MYTABLE');
    SQL.Add('set username='+QuotedStr(NewUserName));
    SQL.Add(',password='+QuotedStr(NewPassword));
    SQL.Add('where username='+QuotedStr(ACurrentUserName));
    ExecSQL;
    Res:=true;
  end;
  except
  Res:=False;
  end ;
  Result:=Res;
end;

Try ... 的使用是否足以知道“ExecSQL”何时成功或失败?

或者还有其他更好的方法吗?

谢谢

【问题讨论】:

  • 定义“成功”和“失败”。
  • 您是否尝试使用 [username] 而不是 username 来保留用户名。
  • 这个函数给出了结果,但我想知道的是:Try ...的使用是否足以知道“ExecSQL”何时成功或失败?

标签: sql delphi ms-access


【解决方案1】:

如果没有引发异常,您可能希望认为更新成功。这意味着数据库可以响应并解析并执行您的语句而不会出现语法错误。

在如图所示的语句中,您可能还想确保更新了一行,因为我认为这是您的意图。

要检查这一点,您可以使用 ExecSQL 方法的结果,该方法返回受语句执行影响的行数。因此,您可以将代码更改为:

begin
  with MyQuery do
  begin
    Active := false;
    SQL.Clear;
    SQL.Add('Update MYTABLE');
    SQL.Add('set username='+QuotedStr(NewUserName));
    SQL.Add(',password='+QuotedStr(NewPassword));
    SQL.Add('where username='+QuotedStr(ACurrentUserName));
    Result := ExecSQL = 1; //exactly 1 row updated
  end;
end;

我还更改了无条件异常处理程序,因为它可能不是处理任何异常的合适位置,并且还删除了存储结果的局部变量,因为这确实没有必要。

阅读您添加的文字并重新思考您的问题后:

Try ... 的使用是否足以知道“ExecSQL”何时成功或失败?

对于异常处理和从此例程返回布尔值,您确实必须改变主意。异常是作为一个全新的概念引入的,关于如何解决程序中的异常和错误情况,但你正在扼杀这种全新的(恕我直言)方法并诉诸旧方法来返回一个指示成功或失败的值。

尤其是 try/exception 块吃掉任何异常是一种不好的做法,因为您将杀死可能由于太多原因引发的异常:内存不足、网络问题(如与数据库的连接丢失等)。

您必须重新考虑您的方法,并在应用程序的适当级别处理这些异常或错误情况。

我的建议是:

  • 把这个从函数改成过程,新的约定是:只有成功才返回,否则抛出异常。
  • 如果发生异常,让它跳出常规并在其他地方处理这种情况
  • 引发您自己的异常,以防没有准确更新 1 行
  • 更改查询以使用参数(避免 sql 注入)

例程可能如下所示:

procedure TMySecurityManager.ChangeUserNameAndPassword();
begin
  MyQuery.SQL.Text := 'Update MYTABLE'
              + '   set username = :NewUserName'
              + '       , password = :NewPassword'
              + ' where username = :username';
  MyQuery.Params.ParamByName('NewUserName').AsString := NewUserName;
  MyQuery.Params.ParamByName('NewPassword').AsString := NewPassword;
  MyQuery.Params.ParamByName('username').AsString := ACurrentUserName;
  if MyQuery.ExecSQL <> 1 then
      raise EUpdateFailed.Create('A internal error occurred while updating the username and password');
  //EUpdateFailed is a hypotetical exception class you defined.
end;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-19
    • 2019-02-09
    • 1970-01-01
    相关资源
    最近更新 更多