Avatar billede fhansen Praktikant
05. november 2006 - 23:34 Der er 11 kommentarer

Dato i SQL string

Hejsa.

Jeg bruger en procedure til at at loade forskellige SQL strings, nu vil jeg gerne kunne søge efter poster med en dato der er mindre end dags dato, men får en fejl.

LoadClientSql('SELECT  * FROM Kunder, leje '+
                'WHERE Tdato < '+DateToStr(Now) +
                ' AND  nummer = kunde '+
                'ORDER BY %S','nummer');


LoadClientSql bliver læst ind i en Query med format functionen.

Hvordan fixer jeg dette.


Hilsen

Finn
Avatar billede thesurfer Nybegynder
05. november 2006 - 23:53 #1
Du skriver ikke hvilken slags SQL database det er.. de meste brugte er nok MySQL og MSSQL..

MySQL tager datoformatet på en bestemt format.. mener at det er yyyy-mm-dd.. men kan ikke huske det..

Du kan højst sandsynlig få SQL'en til at konverter datoen med:

' WHERE Tdato < #' + DateToStr(now) + '# and

Jeg programmerer ikke i Delphi, men det er en generel SQL formattering..
Avatar billede thesurfer Nybegynder
05. november 2006 - 23:55 #2
Du kan vist bare bruge CURDATE() i SQL:

' WHERE Tdato < CURDATE() and

Ifølge: http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html
Avatar billede hrc Mester
07. november 2006 - 10:53 #3
Nu bruger du en hjemmestikket rutine til at foretage den query - og så har du problemet med at bruge format-funktionen i Queries fremfor at bruge Query.Params. Du burde omskrive det til at modtage parametre, for så skal du ikke bekymre dig om datoformater eller om der skal " eller ' omkring en streng/dato.

CURDATE snupper din database-servers dato; ikke nødvendigvis samme som datoen på din maskine (hvis eksempelvis serverens ur ikke passer eller den står i Kina)

Du burde også lade være med at bruge *, men angive felterne du skal bruge; din query risikerer at blive ret massiv.
I den forbindelse: Mangler du ikke at joine kunder og leje?

Da du vælger sorteringen kan du ikke helt undgå format'en.

aQuerySt :=
'SELECT * FROM kunder, leje'+
'  WHERE (tdato < :tdato'+
'    AND (nummer = kunde'+
'  ORDER BY %S',nummer)';

I mine datamoduler har jeg følgende lille praktiske rutine:

procedure TDM.SetParam(aParameter: TParameter;
                      const aValue: Variant;
                      const aSetNull: boolean);
begin
  if aSetNull then
    aParameter.Clear // MS-SQL: Value := Null (inkludér Variants-unitten)
  else
    aParameter.Value := aValue;
end;

Min Query er opbygget således:

  Query.SQL.Text := format(aQuerySt,[aFiendName]);
  DM.SetParam(Query.ParamByName('tdato'),ftDateTime,DateOf(now));
Avatar billede fhansen Praktikant
07. november 2006 - 19:44 #4
Hej hrc.

1. Ja jeg kan få den til at virke ved at bruge param, men ideen er at ændre programmet til MySql, hvis en række ændringer kommer til at fungere, i øjeblikket bliver der brugt Paradox,

2. Jeg skal bruge alle felter, derfor *.

3. Jeg har endnu ikke fundet ud af at bruge join.


Det ender jo nok med at starte på en frisk med programmet.

Hilsen

Finn
Avatar billede hrc Mester
08. november 2006 - 09:06 #5
Hvis du har to tabeller: kunder og leje der hver har en primærnøgle der hedder ID og leje bundet til kunder via en fremmednøgle

create table kunder
{
  ID int identify(1,1),
  data varchar(100),
  primary key(ID)
)

create table leje
{
  ID int identify(1,1), // Identity virker i MSSql
  kunder_ID int not null,
  data varchar(100),
  tdato date,
  foreign key (kunder_ID) references kunder(ID),
  primary key(ID)
)

... så kan du joine dem på følgende måde

SELECT * FROM
  kunder k
  join leje l on (l.kunder_ID = k.ID)
  WHERE (l.tdato < :tdato)
  ORDER BY %S',nummer)

Det kan godt være at relationen hænger på den anden vej, men det da et specifikt eksempel.

Hvis du skulle lave en procedure til at lave forespørgslen så kunne du lave noget i retning af dette (ikke så kønt, men det vil virke). Data skal komme i samme rækkefølge som parametrene. Det er ikke testet og måske kan man ikke tildele uden at behøve at angive datatypen på parametrene - det må du selv teste (men det kan løses ret let)

function LoadClientSql(const aQuery, aOrderField : string; const aParams : array of const) : TADOQuery;
var
  i : integer;
begin
  result := TADOQuery.Create(nil);
  result.Connection := ADOConnection;
  result.SQL.Text := trim(format(aQuery,[aOrderField]));
  for i := low(aParams) to high(aParams) do
    result.Parameters.Params[i].Value := aParams[i];
  result.Open;
end;
Avatar billede fhansen Praktikant
09. november 2006 - 18:29 #6
Vil prøve at lege med det lidt i næste uge, for har lige fundet et andet problem med
TupdateSql, jeg vil lige rejse et nyt spørgsmål med dette.

Men hvad med inner join og outer join.


Hilsen


Finn
Avatar billede hrc Mester
09. november 2006 - 22:32 #7
Og left og right join; det varierer lidt hvad de kaldes. Jeg mener at "Left" og "Left inner" er det samme mens "Right" og "Right outer" ditto giver samme resultat.

Givet tabellerne

Tabel1:

ref    tekst    tabel2_ref
--------------------------
1    The    2
2    Quick    NULL
3    Brown    1
4    Fox    NULL
5    Jumps    2
6    Over    NULL
7    The    3
8    Lazy    NULL
9    Dogs    4

Tabel2:

ref    tekst
-------------
1    Eenie
2    Meenie
3    Minie
4    Moe

Hvis du har en simpel join så får du de records der matcher - og ikke andre:

select t1.ref, t1.Tekst, t1.tabel2_ref
  from dbo.Tabel1 t1
  join dbo.Tabel2 t2 on (t2.ref = t1.Tabel2_ref)

Resultat:

ref    tekst    Tabel2_ref
--------------------------
1    The    2
3    Brown    1
5    Jumps    2
7    The    3
9    Dogs    4

Kun de records i tabel1 hvor der er en reference til tabel2 tages med.

En left join mellem de to tabeller:

select t1.ref, t1.Tekst, t1.tabel2_ref
  from dbo.Tabel1 t1
  left join dbo.Tabel2 t2 on (t2.ref = t1.Tabel2_ref)

Resultat:

ref    tekst    Tabel2_ref
--------------------------
1    The    2
2    Quick    NULL
3    Brown    1
4    Fox    NULL
5    Jumps    2
6    Over    NULL
7    The    3
8    Lazy    NULL
9    Dogs    4

Alle records fra Tabel1 kommer med. Bemærk at sorteringsordenen følger tabel1's

En right join mellem de to tabeller:

select t1.ref, t1.Tekst, t1.tabel2_ref
  from dbo.Tabel1 t1
  right join dbo.Tabel2 t2 on (t2.ref = t1.Tabel2_ref)

Resultat:

ref    tekst    Tabel2_ref
--------------------------
3    Brown    1
1    The    2
5    Jumps    2
7    The    3
9    Dogs    4

Alle de records i Tabel2 hvor der er reference mellem den og Tabel1 tages med - men på Tabel2's præmisser. Bemærk at sorteringsordenen er Tabel2's.
Avatar billede fhansen Praktikant
10. november 2006 - 00:24 #8
Ahhh, det skal prøves af, umiddelbart tror at det kan være løsningen til et d andre små problemmer jeg pusler med.

Finn
Avatar billede fhansen Praktikant
15. november 2006 - 23:56 #9
Join er da en dejlig ting, det har løst en del problemer for mig, samt givet en række nye muligheder.
Jeg vil ønske at dette program var skrevt til MySql fra starten, jeg begynder at blive i tvivl jeg ikke bare skulle skrive om til Sql nu i stedet for at vente


Finn
Avatar billede hrc Mester
16. november 2006 - 09:31 #10
Det er svært at sige - hver gang jeg er blevet påtvunget et program med databaseadgang på anden vis end via SQL, så er ansigtet automatisk blevet lagt i "trætte folder". Jeg hader at programmere på den måde - det er omstændigt at omskrive til SQL - og hvis programmet har bare et lille liv, så skal man det engang.
En anden grund til mit "had" er, at i mit første Delphi-job var det SQL og client-server der blev programmeret. Det er viden/teknikker jeg er taknemmelig for og som jeg har bygget videre på. Desværre præger det min entusiasme når jeg ser TTable, TDBGrid eller lignende i brug.
Avatar billede fhansen Praktikant
17. november 2006 - 23:10 #11
*SSS*

Ja vi lærer jo hele tiden
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester