SQL фильтр превращает мою DBGrid в пустую таблицу - PullRequest
0 голосов
/ 01 апреля 2020

Я пытаюсь написать фрагмент кода, который будет принимать ввод пользователя, если значения по умолчанию изменились, и поместить его в оператор SQL.

procedure TfrmHotels.btnFilterClick(Sender: TObject);
  var
    iTest, iErrorCode, iMinStars, iMaxStars, iMinCost, iMaxCost: Integer;

begin
//This is the first thing the SQL does, by filtering the entire database to show all the hotels in the area the user has selected
  with dmCoAdventure do
    begin

      qryCoAdventure.SQL.Clear;
      qryCoAdventure.SQL.Add('SELECT * FROM Hotels WHERE TownName = ' + QuotedStr(frmTowns.sTown));
      qryCoAdventure.Open;

    end;
  //If the value changes
  if (spnMinStars.Value <> 0) OR (spnMaxStars.Value <> 0) then
    begin

      if spnMinStars.Value > spnMaxStars.Value then
        begin

          ShowMessage('Min Stars can''t be higher the Max Stars.');
          Exit;

        end
      else
        begin

          iMinStars:= spnMinStars.Value;
          iMaxStars:= spnMaxStars.Value;

          with dmCoAdventure do
            begin
             //Adds the filter
              qryCoAdventure.SQL.Add('AND Stars BETWEEN ' + IntToStr(iMinStars) + ' AND ' + IntToStr(iMaxStars));

              //ShowMessage('AND Stars BETWEEN ' + IntToStr(iMinStars) + ' AND ' + IntToStr(iMaxStars));

            end;

        end;

    end;
 //If the value changes
  if (edtMinCost.Text <> '') AND (edtMaxCost.Text <> '') then
    begin
     //Test that the min value is less than the max value
      if edtMinCost.Text > edtMaxCost.Text then
        begin

          ShowMessage('Min Cost can''t be more then Max Cost.');
          Exit;

        end
      else
        begin
       //Validate that it can change to an integer
          Val(edtMinCost.Text,iTest,iErrorCode);

          if iErrorCode = 0 then
            begin

              Val(edtMaxCost.Text,iTest,iErrorCode);

              if iErrorCode = 0 then
                begin

                  iMinCost:= StrToInt(edtMinCost.Text);
                  iMaxCost:= StrToInt(edtMaxCost.Text);

                  with dmCoAdventure do
                    begin
                        //Adds the filter
                      qryCoAdventure.SQL.Add('AND CostPNight BETWEEN ' + IntToStr(iMinCost) + ' AND ' + IntToStr(iMaxCost));

                    end;

                end
              else
                begin

                  ShowMessage('Min and Max values should both be numbers.');

                end;

            end
          else
            begin

              ShowMessage('Min and Max values should both be numbers.');

            end;

        end;

    end;

end;

В момент добавления Фильтры мин и макс звезд или даже фильтр затрат сетка становится пустой и не отображает никаких данных. Я попытался изменить значение «ween »только для операторов« <»или«> », и я все еще получаю тот же эффект. Я думал, что это может быть связано с тем, как настроен SQL, но я недостаточно осведомлен, чтобы знать, где я ошибся.

1 Ответ

0 голосов
/ 03 апреля 2020

Все комментарии Кена Уайта верны. Поскольку вы, очевидно, боретесь с тем, как претворить в жизнь то, что мы сказали, на практике, вот пример проекта, который настолько прост, насколько возможно, который показывает, как правильно использовать параметры в запросе Sql. Для этого:

  1. Создайте новый Delphi проект VCL и добавьте в его форму

    • AdoConnection1, для которого ConnectionString установлено подключение к вашему Sql сервер
    • AdoQuery1, который использует AdoConnection1
    • DataSource1 со свойством DataSet, установленным в AdoQuery1
    • DBGrid1, свойство DataSource которого установлено в DataSource1
    • Две кнопки с именем btnCreateTable и btnApplyFilter с обработчиками событий, как показано в приведенном ниже коде.
  2. Измените форму проекта, включив в нее код, показанный ниже.

  3. Скомпилируйте и запустите проект.

  4. Нажмите btnCreateTable. Sql, который он выполняет, написан для сервера Microsoft Sql, поэтому может работать некорректно на 100%, если вы используете сервер другого типа. Если какой-либо из операторов sQl создает исключение, редактируйте константы sCreateTable и / или sInsertRows, пока оба не будут выполнены правильно. Если это слишком много проблем, просто создайте таблицу отелей вручную и вставьте строки вручную.

    Как только у вас появится таблица отелей со строками данных в ней ...

  5. Нажмите btnApplyFilter

  6. Сетка должна отображать только строки 3 и 4. Если это не так, вы сделали что-то не так, так что проверьте все, исправьте все ошибки и попробуйте снова.

Теперь внимательно изучите код в процедуре TForm1.ApplyFilter.

Константа Filter Sql указывает параметризованный запрос Sql, параметры которого являются требуемое минимальное и максимальное количество звездочек: эти параметры: Min и: Max.

После того, как фильтр Sql был предоставлен AdoQuery1, код устанавливает для AdoQuery1.Prepared значение True; для этого нужно отправить запрос на сервер Sql, чтобы проанализировать его и настроить запрос на выполнение; на самом деле он не выполняет запрос. Запрос, который готовит сервер, включает значения Min и Max в качестве «заполнителей», и сервер ожидает получения значений этих параметров, прежде чем он фактически выполнит запрос. Это то, что в строках

AdoQuery1.Parameters.ParamByName('Min').Value := MinStars;
AdoQuery1.Parameters.ParamByName('Max').Value := MaxStars;

Наконец, вызов

AdoQuery1.Open

говорит серверу фактически выполнить запрос, и, как только сервер это сделает, AdoQuery1 считывает результаты с сервера и отображает их в сетке.

код

const
  sCreateTable = 'create table Hotels(ID Int primary key, Name NVarChar(20), Stars int)';

  sInsertRows =  'insert Hotels(ID, Name, Stars) values(1, ''One'', 1)'
  +  ' insert Hotels(ID, Name, Stars) values(2, ''Two'', 5)'
  +  ' insert Hotels(ID, Name, Stars) values(3, ''Three'', 3)'
  +  ' insert Hotels(ID, Name, Stars) values(4, ''Four'', 2)';

procedure TForm1.ApplyFilter(MinStars, MaxStars : Integer);
const
  FilterSql = 'select * from Hotels where Stars between :Min and :Max';
begin
  if AdoQuery1.Active then
    AdoQuery1.Close;

  AdoQuery1.Sql.Text := FilterSql;
  AdoQuery1.Prepared := True;
  AdoQuery1.Parameters.ParamByName('Min').Value := MinStars;
  AdoQuery1.Parameters.ParamByName('Max').Value := MaxStars;

  AdoQuery1.Open;
end;

procedure TForm1.btnApplyFilterClick(Sender: TObject);
begin
  ApplyFilter(2, 3);
end;

procedure TForm1.btnCreateTableClick(Sender: TObject);
begin
  AdoConnection1.Execute(sCreateTable);
  AdoConnection1.Execute(sInsertRows);
end;
...