您好我有这个函数来使用TUniQuery更新我的Access数据库:
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”成功或失败?
还是有其他更好的方法吗?
谢谢
答案 0 :(得分:9)
如果没有引发异常,您可能需要考虑更新成功。这意味着数据库响应并解析并执行您的语句,而不会出现语法错误。
在如图所示的声明中,您可能还需要确保一行已更新,因为我认为这是您的意图。
要检查这一点,您可以求助于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”成功或失败?
你真的必须改变你对异常处理的想法,并从这个例程返回一个布尔值。例外是作为一个关于如何解决程序中的异常和错误情况的全新概念而引入的,但是你正在杀死这整个新的(和更好的恕我直言)方法,并采用旧的方式返回一个表示成功或失败的值。 / p>
特别是一个吃掉任何异常的try/exception
块是一种不好的做法,因为你会杀死可能由于太多原因而引发的异常:内存不足,网络问题,例如连接丢失到数据库等等。 / p>
您必须重新考虑您的方法,并在您的应用程序的适当级别处理这些异常或错误条件。
我的建议是:
例程可能如下所示:
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;