Why, if adding a value to a database through a variable, then “ADOQuery1” is added, and if directly, then a correct value?

Viewed 85

There is such a code.

procedure TForm1.FramePositionsAdd1ButtonAddClick(Sender: TObject);
var
  Name: String;
  begin
    Name := FramePositionsAdd1.EditName.Text;

    with FramePositionsAdd1.ADOQuery1 do
    begin;
      SQL.Clear;
      SQL.Text := 'INSERT INTO Должности ' +
      '(Наименование) ' +
      'VALUES ' +
      '(:title)';
      Parameters.ParamByName('title').Value := Name;
      ExecSQL;
    end;
end;

The value is added to the database, but instead of FramePositionsAdd1.EditName.Text the string ADOQuery1 is added. I tried to remove the Name variable. One line changes:

Parameters.ParamByName('title').Value := FramePositionsAdd1.EditName.Text;

And everything work correctly. What is the problem?

1 Answers

Your use of with is causing the reference to Name to resolve to AdoQuery1.Name instead of your local variable Name.

with FramePOstitionsAdd1.AdoQuery1 do
begin
  // Name used here, because of the with, refers to the object in the
  // with statement and not the local variable declared outside the
  // with block.
end;

Either change the name of the variable to something else, or (better) stop using with because of the side effects it can have that cause issues like this.

procedure TForm1.FramePositionsAdd1ButtonAddClick(Sender: TObject);
var
  Title: String;
begin
  Title := FramePositionsAdd1.EditName.Text;

  with FramePositionsAdd1.ADOQuery1 do
  begin
    SQL.Clear;
    SQL.Text := 'INSERT INTO Должности ' +
      '(Наименование) ' +
      'VALUES ' +
      '(:title)';
    Parameters.ParamByName('title').Value := Title;
    ExecSQL;
  end;
end;

Better solution that prevents future problems of the same nature due to edits:

procedure TForm1.FramePositionsAdd1ButtonAddClick(Sender: TObject);
var
  Name: String
  Qry: TAdoQuery;
begin
  Name := FramePositionsAdd1.EditName.Text;
  // Get a local reference to your query
  Qry := FramePositionsAdd1.ADOQuery1;

  // Use that local reference
  Qry.SQL.Clear;
  Qry.SQL.Text := 'INSERT INTO Должности ' +
      '(Наименование) ' +
      'VALUES ' +
      '(:title)';
  Qry.Parameters.ParamByName('title').Value := Name;
  Qry.ExecSQL;
  // DO NOT free or nil Qry here. It is just a pointer to the original,
  // not a new object, and freeing it will free the original query instead.
end;
Related