如果没有引发异常,您可能希望认为更新成功。这意味着数据库可以响应并解析并执行您的语句,而不会出现语法错误。
在如图所示的语句中,您可能还想确保恰好更新了一行,因为我认为这是您的意图。
要检查这一点,您可以使用 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...except 足以知道“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;