04. oktober 2000 - 14:15Der er
20 kommentarer og 5 løsninger
Søgning i database?
Jeg skal bruge en kode der kan søge i en database, min db er en tabel fra bde, paradox 7. Jeg skal gerne kunne søge både på navn og nr. dvs 2 forskellige felter!
Jeg foretrækker nu godt nok at benytte en Query når jeg skal lave søgninger i en tabel. TTables har nogle rutiner (Find, Locate - søg dem i online hjælpen eller skriv igen hvis du vil ha\' et eksempel).
Nedenfor er der et eksempel på hvorledes du kan benytte en query.
Start på en ny, tom form. Klasy en TQuery component på formen samt en datasource. sæt datasourcens Dataset property til Query1. Sæt en DBGrid på formen og sæt dens datasource property til Datasource1. Placer derefter en button på formen og i dens OnClick event skriver du følgende kode:
Query1.Close; Query1.DatabaseName := \'DBDEMOS\'; Query1.SQL.Clear; Query1.SQL.Add(\'Select *\'); Query1.SQL.Add(\'From Customer\'); Query1.SQL.Add(\'Where CustNo = :CustNo\'); Query1.SQL.Add(\' Or Company = :CompName\'); Query1.SQL.Add(\' Or City = :CityName\');
Jeg har lavet en TTable version. Programmet er lidt omfattende, idet det indeholder SetRange, Locate, Find og FindNearest metoderne - det skulle give dig mulighed for at komme vidre - så derfor har jeg inkluderet kode for både form og unit.
Kig på det og råb op hvis du har spørgsmål.
Delphi.
PS: Jeg har fri i morgen (fredag), så der er jeg er måske lidt fraværende....
//****** Formens kode (som text) object Form1: TForm1 Left = 676 Top = 505 Width = 870 Height = 640 Caption = \'Form1\' Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = \'MS Sans Serif\' Font.Style = [] OldCreateOrder = False PixelsPerInch = 96 TextHeight = 13 object DBGrid1: TDBGrid Left = 16 Top = 8 Width = 761 Height = 345 DataSource = DataSource1 TabOrder = 0 TitleFont.Charset = DEFAULT_CHARSET TitleFont.Color = clWindowText TitleFont.Height = -11 TitleFont.Name = \'MS Sans Serif\' TitleFont.Style = [] end object buRange: TButton Left = 24 Top = 376 Width = 75 Height = 25 Caption = \'&Apply Range\' TabOrder = 1 OnClick = buRangeClick end object buLocate: TButton Left = 120 Top = 376 Width = 75 Height = 25 Caption = \'&Locate\' TabOrder = 2 OnClick = buLocateClick end object buFind: TButton Left = 208 Top = 376 Width = 75 Height = 25 Caption = \'&Find 1560\' TabOrder = 3 OnClick = buFindClick end object buFindNearest: TButton Left = 296 Top = 376 Width = 113 Height = 25 Caption = \'Find&Nearest Uni\' TabOrder = 4 OnClick = buFindNearestClick end object Table1: TTable Active = True DatabaseName = \'DBDEMOS\' TableName = \'customer.db\' Left = 56 Top = 40 end object DataSource1: TDataSource DataSet = Table1 Left = 56 Top = 72 end end
// SetRange eksempel. Bemærk at denne metode ikke // decideret finder noget du søger efter. Den begrænser // blot hvor stor en mængde af data der vises fra tabellen. // Eksemplet bygger på on-line hjælpen. procedure TForm1.buRangeClick(Sender: TObject); begin Table1.Active := False; Table1.DatabaseName := \'DBDemos\'; Table1.TableName := \'Customer.db\'; Table1.IndexName := \'ByCompany\'; Table1.Active := True;
if buRange.Caption = \'&Apply Range\' then begin Table1.SetRange([\'a\'],[\'c\']);
buRange.Caption := \'&Drop Range\'; end else begin Table1.CancelRange; Table1.Refresh; buRange.Caption := \'&Apply Range\'; end; end;
// Eksempel hvor der tabellens cursor flyttes til // de specifikt søgte data. // Fordelen ved Locate er at du kan søge på alle // kolonner, ikke kun dem der er index. Ulempen er, // sommed FindKey, at du skal kende de helt rigtige // søgekriterier. Fx. Kan du ikke søge på \'UNI\' // for at finde firmate \'UNISCO\'.
procedure TForm1.buLocateClick(Sender: TObject); begin Table1.Locate(\'CustNo;Company;\',VarArrayOf([\'1380\',\'Blue Jack Aqua Center\']), [loPartialKey]); end;
// FindKey eksempel, lidt lige som Locate, men man // kan kun søge på index kolonner - det kan // udemærket være et kombineret index, men et sådant // findex bare ikke i DBDEMOS, Customer tabellen. // Her beder jeg tabellen om at flytte cursoren // til det firma der har nr. 1560 procedure TForm1.buFindClick(Sender: TObject); begin Table1.IndexFieldNames := \'CustNo\'; Table1.FindKey([\'1560\']); end;
// Som FindKey, men finder første record, der matcher // eller er \"højere\" end søgekriterierne. // Her søges på første firma hvis navn starter // med \'Uni\' - eller noget højere. procedure TForm1.buFindNearestClick(Sender: TObject); begin Table1.IndexFieldNames := \'Company\'; Table1.FindNearest([\'Uni\']); end;
Du kan også gøre den uden brug af parametre: <SNIP> Query1.Close; Query1.DatabaseName := \'DBDEMOS\'; Query1.SQL.Clear; Query1.SQL.Add(\'Select *\'); Query1.SQL.Add(\'From Customer\'); Query1.SQL.Add(\'Where (CustNo = 1221)\'); Query1.SQL.Add(\' Or (Company = \'+chr(39)+\'Unisco\'+Chr(39)+\')\'); Query1.SQL.Add(\' Or (City = \'+chr(39)+\'Freeport\'+Chr(39)+\')\'); Query1.Open; </SNIP>
Den eneste forskel er at parametrene gør det lidt nemmere (smag og behag) men resultatet er det samme (dog har jeg brug paranteser \"omkring where-delen\").
Jo da, man kan se\'følig gøre det med indlagte streng konstanter, som ved pellelil, eller med varaiable (med parametre er nu det der er mest \"rigtigt\"). Jeg mener kun at paranteser forstyrer - de er ikke nødvendige i dette eksempel og ikke påkrævet af SQL.
Eksempel med variable søgeværdier (og en Query).
Var CustNo : Integer; CompName : String; CityName : String;
Begin CustNo := 1221; CompName := \'Unisco\'; CityName := Edit1.Text; // Fx. en TEdit på formen.
Query1.Close; Query1.DatabaseName := \'DBDEMOS\'; Query1.SQL.Clear; Query1.SQL.Add(\'Select *\'); Query1.SQL.Add(\'From Customer\'); Query1.SQL.Add(\'Where CustNo = \'+IntToStr(CustNo)); Query1.SQL.Add(\' Or Company = \'+CompName); Query1.SQL.Add(\' Or City = \'+CityName);
Query1.Open; End;
(Ud af hånden og ned på tastaturet => ikke afprøvet!)
delphi> du skal lige have et sæt anførsels-tegn omkring dine strenge, og jeg må indrømme at jeg ikke er klar over om parenteser omkring dine or-dele er påkrævet, men god/gammel vane gør at jeg altid sætter dem !?
Du har ret der mangeler gåseøjne eller anførselstegn (afhængigt af bagvedliggende DB-system).
Paranteser er ikke nødvendige. De skal dog bruges hvor man vil gøre forskel på den normale vægtning af et udtryk. Fx. er der stor forskel på følgende udtryk:
1: Where A=1 OR B=2 AND C=3
2: Where (A=1 OR B=2) AND C=3
Eksempel 1: er underforstået det samme som:
Where A=1 OR (B=2 AND C=3)
Fidusen er, at du i dit eksemple skrev:
Where (A=1) OR (B=2) AND (C=3)
Hvilket ikker er noget du har lært fra SQL, men er et krav under Delphi\'s object pascal (i en If sætning, se\'følig).
delphi> Du behøver ikke at lære mig om boolskalgebra eller Delphi\'s implementering af samme, men jeg er ikke klar over hvad SQL \"kræver\". Som jeg sagde i dag er det bare en god vane, men alligevel tak for din indsats :-)
Hør lige her, jeg skal bruge det lille rene stump jeg skal bruge til at søge i en database, jeg skal bruge en edit felt, og en knap, når jeg skirver noget i edit og trykker på knappen viser den hvad den har fundet i dbgridet. Når i har det får i de 120 point. I har endnu ikke svaret optimalt, da ingenting virker. Jeg bruger delphi 5!
SQL foresprøgsler virker ikke på en TTable, og de eksempler Delphi og jeg har vist er bygget ud fra en af Delphi\'s demodatabaser, så naturligvis virker det ikke på din tabel.
Hvis du vil have et eksempel der viser nøjagtigt hvordan det skal skrives så er du nødt til at oplyse felt-beskrivelsen (felt: navne, typer, index und so weiter).
Hvis du vil/kan læse mellem linierne så er nedenstående fra Delphi\'s hjælp og beskriver/viser brugen af Locate (på en TTable): <SNIP> with CustTable do Locate(\'Company;Contact;Phone\', VarArrayOf([\'Sight Diver\', \'P\', \'408-431-1000\']), [loPartialKey]); </SNIP>
Hvis du vil have din grid til kun at vise de poser (altså en filtrering frem for en søgning) så skal du i stedet (når vi taler TTable) bruge Event\'en OnFilterRecord.
Mine felter man skal søge i hedder, \"Editdelnr\" og \"Editdelnavn\". Jeg skal bruge en søgestring til en Ttable, jeg ved det skal kunne lade sig gøre. Alt det der med TQuery kan du glemme, oliver. Kan I ikke give mig en kode der lige passer ind, jeg skal bruge den meget hurtigt, på forhånd tak.
Lad mig lige spørge (bare en gang) HVORFOR vil du ikke gøre brug af en TQuery?. Jeg mener hvis du skal slå et søm i vægen så bruger du vel heller ikke en sav !?
Ovenstående eksempel kan nemt tilrettes til det du har brug for. Jeg gætter på at de felter du indtaster i er dem du nævner some \"Editdelnr\" og \"Editdelnavn\", men du skriver således ikke hvad de hedder i tabellen, så jeg har gættet på at de hedder \"delnr\" og \"delnavn\" (alternativet var \"John\" og \"Aage\" <G>).
<SNIP> with Table1 do Locate(\'delnr;delnavn\', VarArrayOf([EditDelNr.Text, EditDelNavn.Text]), [loPartialKey]); </SNIP>
Jeg kan varmt anbefale at du prøver at læse lidt i Delphi\'s hjælp - den er ikke helt ubrugelig.
Denne function leder i tabellen >>Tablelokaler<< i attributten >>værelsesnummer<< efter >>2<<. hvis fundet sættes databasens cursor på recorden, ellers returneres false. Håber forklaringen er fyldestgørende :=)
procedure GetFirst(var Navn:string; var FoundData:boolean); begin FoundData := False; With DataModule1.Table1 do begin First; if not EOF then begin Navn := FieldByName(\'SName\').AsString; FoundData := True; end; end; end;
procedure GetNext(var Navn:string; var FoundData:boolean); begin FoundData := False; with DataModule1.Table1 do begin Next; if not EOF then begin Navn := FieldByName(\'SName\').AsString; FoundData := True; end; end; end;
At gøre det helt nemt ville være at bruge følgende:
Table1.Setkey; Table1.IndexName := \'Feltnavn\'; //Andet end primary Index Table1.FieldByName(\'Feltnavn\').AsString := Edit1.text; Table1.GotoNearest
eller
Table1.FindNearest([edit1.text]);
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.