11. september 2004 - 19:43Der er
23 kommentarer og 1 løsning
sql spørgsmål
hejsa gutter... jeg er ved at lave et laver simplet faktureings og lager styring til en selv stændig virksom hed... men jeg er låbet ind i et lille problem... jeg har lavet det sådan at når man har lavet en faktura skal man vælge at bogføre den. og så skal den trække de forskellige ting ud af lagert.. jeg har 10 linjer med vare på en fakura.. jeg finde vare i varedatabasen med denne sql sætning...
frmvare.SQLvare.SQL.Add('Select * from vare where varenr like ' + '"' + frmfaktura.TXTvarenr1.Text + '"' + 'order by varenr');
den finder fint vare en men jeg kan ikke få lov til at ændre hvormange der er på lager...
Jeg mener der finde en sql sætning som både kan finde en varenr og samtid ændre varebeholdingen..
jeg får en fejl frmvare.SQLvare.sql.add('UPDATE vare SET lager = currtostr(regn2) WHERE varenr like ' + '"' + frmfaktura.TXTvarenr1.Text + '"' + 'order by varenr');
frmvare.sqlvare.Close; frmvare.SQLvare.SQL.Clear; frmvare.SQLvare.SQL.Add('Select * from vare where varenr like ' + '"' + frmfaktura.TXTvarenr1.Text + '"' + 'order by varenr'); //frmvare.SQLvare.sql.add('UPDATE vare SET lager = ' + currtostr(regn2) + 'WHERE varenr like "' + frmfaktura.TXTvarenr1.Text + '"'); frmvare.SQLvare.ExecSQL; frmvare.dsource.Enabled :=true; frmvare.sqlvare.Active := true; regn2 := strtocurr(frmvare.txtlager.Text) - strtocurr(txtantal1.Text); //udregning af hvad ny lager skal være MessageDlg(currtostr(regn2), mtInformation,[mbOk], 0); // en tjek box til at se om den regner det tigtig ud
sidste problem den give en fejl invalid field name.. jeg har tjekke alle de paser er det for de variabel strings tpvarenr og tpbes og tppris og tplager.. at jeg ikke har skrevet dem tigtig ind.. de inde holder data fra den post jeg lige har slettet minus de der er solg så lager er minder
frmvare.SQLvare.SQL.Add('INSERT INTO vare(varenr,beskrivelse,pris,lager) VALUES (tpvarenr,tpbes,tppris,tplager)');
hvis jeg bruger dirkte tekst virker der godt nok frmvare.SQLvare.SQL.Add('INSERT INTO vare(varenr,beskrivelse,pris,lager) VALUES ("323-323","done","9999","112")');
Mig bekendt er der ikke en SQL-sætning der kan lave opslag og opdatere et felt på én gang, men du kan godt lave en UPDATE der opdaterer på grundlag af en SELECT ... dvs. det kan du ikke i alle gratis databaser. I MySql er det f.eks. et problem. I øvrigt gør du det allererede i dit eksempel med din "update ... where"
Nu kommer så kritikken:
Du bruger "like" i en UPDATE, på noget som burde være en unik nøgle, varenummeret - hvilket det sikkert også er, så drop "like" der mest bruges i forbindelse med søgninger hvor der kommer 1 eller flere rækker (tuppler - var det ikke det lærebogen kaldte dem?) retur. Det er tungt af h. til.
I dit eksempel søger du vha "like" og hvis brugeren skriver 12% (eller 12* i access), så får du flere records retur - flere records som du derefter vil opdatere. Det kan kun gå galt.
Du genererer en SQL-sætning vha. en streng hvor alle parametrene sættes ind. Det er også noget skod, idet du får problemer med strenge, datoer og decimaltal. Eksempelvis skal du kunne håndtere en streng der ser sådan ud: "Metabo Akku 1234 'The spinner' boremaskine". Der er stor fare for at brugeren taster " eller ' i den tekst der skal gemmes. Ligeledes vil et decimaltal kunne fejle idet du bruger komma, mens databasen vil have punktummer. Løsningen er af bruge parametre i stedet:
var // Strengt taget OK med en strengnøgle når det er et varenummer - men pas på // med æøå og lignende. Lidt ulogisk at vareNUMMERET er en streng VareNr : string; begin with frmVare.SQLvare do begin { Det kan da ikke være meningen at en søgning, der kan returnere 0..n rækker, alle skal opdateres, vel? Derfor, skod denne query (men sådan kunne den se ud) { SQL.Text := 'Select * from Vare where VareNr = :Vare order by VareNr'; ParamByName('Vare').AsString := frmfaktura.TXTvarenr1.Text; // Kan også hedde Parameters.ParamBy ... afh. valg af komponent Open;
Antager at dette her kunne klare sagen idet varenummeret fra din TEdit må være unikt:
with frmVare.SQLvare do begin try SQL.Text := update vare set lager = :Regn2 where VareNr = :VareNr'; ParamByName('Regn2').AsInteger := StrToInt(TxtAntal1.Text); ParamByName('VareNr').AsString := frmfaktura.TXTvarenr1.Text; except // Kender ikke din database, men der kommer en specifik fejl på ”Not found”, // og den burde du håndtere, resten skal reraises (m. raise). on E: exception do MessageDlg(e.message,mtError,[mbOK],0); end; ExecSQL; end;
Jeg fortsætter: Du bruger også "select * from ..". Forestil dig, at du vil have alle varenumrene hentet ud (select * from vare). Med ovenstående får du en masse overflødigt skrammel retur sammen med varenumrene. Derfor: Hent kun de ting som du skal bruge ("select VareNr from ..."). Det kan jo være at programmet kommer til at køre over en svag trådløs forbindelse eller lignende hvor datamængden pludselig bliver vigtig. Det er dårlig programmeringspraksis.
Sammenfattende, og jeg synes det bør siges: Med den manglende kvalitet som dit kodeeksempel bærer præg af, så tror jeg du gaber over en stor opgave. Dine evner som systemudvikler er ikke gode nok. Det minder om en revisor der prøver at programmere – og der er nogle af os der har set kodningen bag Damgaard/Microsofts C5’er (pyha)…
Det er halvhårde ord, men jeg har givet dig en objektiv kritik. Held og lykke med projektet. Jeg frygter du behøver det ;-)
arne_v: Ja, jeg ved det godt, eller han kunne såmænd kravle. Jeg gjorde store anstrengelser for at give ham en objektiv vurdering ud fra det han klistrede ind på Eksperten - og jeg kunne ikke lide det.
Delphi er en fed og kraftfuld programmeringsplatform og den skal ingen besudle med nybegynderprogrammering. Ja, jeg er ret dedikeret... Godnat.
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.