Portál AbcLinuxu, 19. dubna 2024 14:10


Dotaz: Stránkování dat z MySQL v aplikaci

9.9.2010 11:35 PetrHL | skóre: 17 | blog: petr_h | Neratovice
Stránkování dat z MySQL v aplikaci
Přečteno: 427×
Odpovědět | Admin
Dobrý den,

mám aplikaci, která pracuje s daty v MySQL. Jedna tabulka má kolem 100k záznamů a já bych rád tyto záznamy zobrazil postupně uživateli.
Mé řešení:

Po spuštění aplikace zobrazím prvních 500 záznamů. Když uživatel začne rolovat v gridu a dostane se na konec, načtu následujících 500 záznamů. Pokud se vrací zpět, načtu předchozí záznamy atd. Funguje to velice pěkně a rychle. Používám na to LIMIT a OFFSET. Je tu ale problém.

Tabulka je nějak setříděná. Uživatel chce editovat záznam. Pokud opraví položku, podle které se tabulka třídí, položka se posune na jinou pozici, takže se dostane mimo hranice stanovené LIMIT a OFFSET. Jak se mám na tento záznam po ukončení editace vrátit? Jak mám zjistit, kterou stránku mu mám pomocí LIMIT a OFFSET zobrazit (kurzor na záznam už pak přesunu pomocí sekvenčního vyhledání pod ID)? Máte, prosím, nějaký nápad?

Díky moc!
Petr
"Do, or do not. There is no 'try.'" -- Jedi Master Yoda | CQRLOG | CQRPROP | HamQTH | Domů

Řešení dotazu:


Nástroje: Začni sledovat (1) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

rADOn avatar 9.9.2010 12:48 rADOn | skóre: 44 | blog: bloK | Praha
Rozbalit Rozbalit vše Re: Stránkování dat z MySQL v aplikaci
Odpovědět | | Sbalit | Link | Blokovat | Admin
select count(*) from table where sort_key < changed_key
a mas pozici.
"2^24 comments ought to be enough for anyone" -- CmdrTaco
Řešení 1× (PetrHL (tazatel))
13.9.2010 10:01 PetrHL | skóre: 17 | blog: petr_h | Neratovice
Rozbalit Rozbalit vše Re: Stránkování dat z MySQL v aplikaci

Díky za radu, pomohlo to. Bohužel pokud je uživatel někde na u konce tabulky, ten select dlouho trvá. Nakonec jsem to vyřešil jinak.
Mé řešení:

procedure TfrmMain.DBGrid1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var
  id : Integer;
  f1 : TDateTime;
  f2 : String;
  f3 : Integer;
begin
  if (key = VK_END) and (Shift = [ssCtrl]) then
  begin
    if cDB_LIMIT > DbRecCount then
      DbOffset := 0
    else
      DbOffset := DbRecCount - cDB_LIMIT;
    try
      Q.DisableControls;
      trQ.Rollback;
      Q.SQL.Text := 'select * from cqrlog_main order by qsodate DESC, time_on DESC LIMIT '+IntToStr(cDB_LIMIT)+' OFFSET '+IntToStr(DbOffset);
      trQ.StartTransaction;
      Q.Open;
      Q.First
    finally
      Q.EnableControls
    end
  end;
  if (key = VK_HOME) and (Shift = [ssCtrl]) then
  begin
    try
      Q.DisableControls;
      trQ.Rollback;
      Q.SQL.Text := 'select * from cqrlog_main order by qsodate DESC, time_on DESC LIMIT '+IntToStr(cDB_LIMIT);
      trQ.StartTransaction;
      Q.Open
    finally
      Q.EnableControls
    end
  end;
  if ((key = VK_UP) or (key = 33)) and Q.BOF then
  begin
    try
      Q.DisableControls;
      id := Q.Fields[0].AsInteger;
      f2 := Q.Fields[2].AsString;
      f1 := Q.Fields[1].AsDateTime;
      Q1.SQL.Text := 'select id_cqrlog_main from cqrlog_main order by qsodate DESC, time_on DESC LIMIT 1';
      trQ1.StartTransaction;
      Q1.Open;
      f3 := Q1.Fields[0].AsInteger;
      trQ1.Rollback;
      Q1.Close;
      if f3=id then //we are on the begining of dataset
        exit;
      Q.Close;
      Q.SQL.Text := 'select * from (select * from cqrlog_main where (qsodate = '+QuotedStr(DateToStr(f1))+
                    'and time_on >= '+QuotedStr(f2)+') or qsodate > '+QuotedStr(DateToStr(f1))+
                    ' order by qsodate, time_on LIMIT '+IntToStr(cDB_LIMIT)+') as foo order by qsodate DESC,time_on DESC';
      trQ.Rollback;
      trQ.StartTransaction;
      Q.Open;
      Q.Last
    finally
      Q.EnableControls
    end
  end;

  if ((key = VK_DOWN) or (key = 34)) and Q.EOF then
  begin
    try
      Q.DisableControls;
      id := Q.Fields[0].AsInteger;
      f2 := Q.Fields[2].AsString;
      f1 := Q.Fields[1].AsDateTime;

      Q1.SQL.Text := 'select id_cqrlog_main from cqrlog_main order by qsodate,time_on LIMIT 1 OFFSET 0';
      trQ1.StartTransaction;
      Q1.Open;
      f3 := Q1.Fields[0].AsInteger;
      Q1.Close;
      trQ1.Rollback;
      if f3=id then //we are on the end of dataset
        exit;
      Q.Close;
      Q.SQL.Text := 'select count(*) from cqrlog_main where (qsodate = '+QuotedStr(DateToStr(f1))+
                    'and time_on <= '+QuotedStr(f2)+') or qsodate < '+QuotedStr(DateToStr(f1))+
                    ' order by qsodate DESC, time_on DESC LIMIT '+IntToStr(cDB_LIMIT);
      Q.Open;
      if Q.Fields[0].AsInteger < cDB_LIMIT then
      begin
        Q.Close;
        Q.SQL.Text := 'select * from (select * from cqrlog_main order by qsodate, time_on LIMIT '+
                       IntToStr(cDB_LIMIT)+') as foo order by qsodate DESC,time_on DESC';
       Q.Open;
       Q.Locate('id_cqrlog_main',id,[])
      end
      else begin
        Q.Close;
        Q.SQL.Text := 'select * from cqrlog_main where (qsodate = '+QuotedStr(DateToStr(f1))+
                      'and time_on <= '+QuotedStr(f2)+') or qsodate < '+QuotedStr(DateToStr(f1))+
                      ' order by qsodate DESC, time_on DESC LIMIT '+IntToStr(cDB_LIMIT);
        Q.Open;
        Q.Locate('id_cqrlog_main',id,[])
      end
    finally
      Q.EnableControls
    end
  end                              

Ještě bude nutné se s tím pohrát, ale funguje to dle očekávání.

"Do, or do not. There is no 'try.'" -- Jedi Master Yoda | CQRLOG | CQRPROP | HamQTH | Domů

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.