Próbuję napisać kod, który przyniesie dane użytkownika, jeśli wartości domyślne zmieniły się i umieścić go w instrukcji 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;

W tej chwili, kiedy dodam filtr Min and Max Stars, a nawet filtr kosztów Grid idzie pusty i nie wyświetla żadnych danych. Próbowałem zmienić "między" na podstawie operatorów "<" lub ">" i nadal otrzymuję ten sam efekt. Moim myśleniem było to, że może być coś wspólnego ze sposobem, w jaki SQL jest skonfigurowany, ale nie jestem wystarczająco kompetentny, aby wiedzieć, gdzie poszedłem nie tak.

0
Jandrie Visagie 1 kwiecień 2020, 19:06

1 odpowiedź

Najlepsza odpowiedź

Wszystkie komentarze Ken White są poprawne. Jak najwyraźniej zmagasz się z tym, jak umieścić to, co powiedzieliśmy w praktyce, oto przykładowy projekt, który jest tak prosty, jak to możliwe, co pokazuje, jak poprawnie używać parametrów w zapytaniu SQL. Śledzić to:

  1. Utwórz nowy projekt Delphi VCL i dodaj do swojej formy

    • adoConnection1, którego Connectionstring jest ustawiony na podłączenie do serwera SQL
    • adquery1, który używa adoconnection1
    • DataSource1 z jego właściwością zestawu danych ustawione na adquery1
    • dbgrid1, którego właściwość DataSource jest ustawiona na DataSource1
    • Dwa przyciski, o nazwie BTNCreatable i Btnapplyfilter z obsługiwaniem zdarzeń, jak pokazano w poniższym kodzie.
  2. Edytuj formularz projektu, aby uwzględnić poniższy kod.

  3. Skompilować i uruchom projekt.

  4. Kliknij BTNCreatable. Ekreuje SQL IT jest napisany dla SQL Server Micricft SQL Może więc nie działać w 100% poprawnie, jeśli używasz innego typu serwera. Jeśli też z instrukcji SQL wytwarza wyjątek, edytuj screatitable i / lub Stałe sinsertrows aż do prawidłowego wykonywania obydwów. Jeśli to jest zbyt duże kłopoty, Po prostu stwórz tabelę hotele ręcznie i ręcznie włóż wiersze.

    Gdy masz tabelę hoteli z wierszami danych w nim ...

  5. Kliknij BtnapplyFilter.

  6. Grid powinna wyświetlać tylko rzędy 3 i 4. Jeśli nie, zrobiłeś Coś nie tak, więc sprawdź wszystko, napraw wszystkie błędy i spróbuj ponownie.

Teraz zbadaj kod procedury TWIR1.applyfilter bardzo ostrożnie.

FiltersQL Constant określa parametryczne zapytanie SQL, parametry są wymaganą minimalną i maksymalną liczbą gwiazd: MIN i: max to te parametry.

Gdy FiltersQL został dostarczony do adquery1, kodu zestawy adquery1.pretared to true; to ma wysłać zapytanie do serwera SQL, aby przeanalizować go i skonfigurować zapytanie do wykonania; Co to nie robi, to faktycznie wykonywać zapytanie. Zapytanie, które przygotowuje serwer obejmuje wartości MIN i MAX jako "symbole zastępcze", a serwer oczekuje, że zostaną usunięte wartości tych parametrów, zanim faktycznie wykonuje zapytanie. To właśnie linie

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

Wreszcie połączenie

AdoQuery1.Open

Opowiada serwerowi, aby faktycznie wykonał zapytanie, a następnie serwer, adquery1 odczytuje wyniki z serwera i wyświetla je w sieci.

Kod

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;
0
MartynA 3 kwiecień 2020, 18:12