Ignorerer den korrekte tilgang
et øjeblik er årsagen til det, at du bruger den forkerte cfsqltype
for parametrene. Så du sender faktisk andre værdier til databasen (og udfører følgelig en anden sammenligning), end du tror. Som et resultat kan forespørgslen ikke finde nogen matchende poster. Det er derfor dit diagram er tomt.
Ved at bruge cf_sql_timestamp
du konverterer "værdien" til et fuldt dato/tidsobjekt. Men ÅR() returnerer kun et firecifret tal. Så du sammenligner æbler og appelsiner. Konceptuelt gør din forespørgsel faktisk dette:
WHERE 2014 = {ts '2009-02-13 23:31:30'}
Grunden til at det ikke giver en fejl er, at dato/tidsværdier gemmes som tal internt. Så du sammenligner faktisk et lille tal (dvs. år) med et rigtig stort tal (dvs. dato/klokkeslæt). Det er klart, at datoværdien vil være meget større, så den vil næsten aldrig matche årstallet. Igen, konceptuelt din forespørgsel gør dette:
WHERE 2014 = 1234567890
Da cfsqltype er valgfri, tror mange mennesker, at det ikke er særlig vigtigt - men det er det.
-
Validering: Ud over dets andre fordele validerer cfqueryparam den leverede "værdi" baseret på
cfsqltype
(dato, dato og klokkeslæt, nummer osv.). Dette sker før sql bliver nogensinde sendt til databasen. Så hvis input er ugyldigt, spilder du ikke et databasekald. Hvis du udelader cfsqltype, eller bare bruger standard dvs. strengen, så mister du den ekstra validering. -
Nøjagtighed Valg af den korrekte cfsqltype sikrer, at du sender den korrekte værdi til databasen. Som vist ovenfor kan brug af den forkerte type få CF til at sende den forkerte værdi til databasen.
cfsqltype
sikrer også, at værdier sendes til databasen i et ikke-tvetydigt format, databasen vil fortolke, som du forventer. Teknisk kunne du sende alt til databasen en streng. Det tvinger dog databasen til at udføre implicit konvertering (normalt uønsket).Med implicit konvertering overlades fortolkningen af strengene helt op til databasen - og den kommer måske ikke altid med det svar, du ville forvente. At indsende datoer som strenge i stedet for datoobjekter er et godt eksempel på det. Hvordan vil den aktuelle database fortolke en datostreng som "05/04/2014"? Som 5. april eller en 4. maj? Det kommer an på. Ændre databasen eller databaseindstillingerne, og resultatet kan blive helt anderledes.
Den eneste måde at sikre ensartede resultater på er at angive den passende cfsqltype. Det skal matche datatypen for sammenligningskolonnen/-funktionen eller i det mindste en tilsvarende type. I tilfælde af YEAR()
, returnerer det et firecifret tal. Så du bør bruge cf_sql_integer
, da Adrian nævnte kommentarerne
. Det samme gælder for din MONTH() sammenligning.
WHERE Year(ColumnName) = <cfqueryparam value="2014" cfsqltye="CF_SQL_INTEGER">
AND Month(ColumnName) = <cfqueryparam value="11" cfsqltye="CF_SQL_INTEGER">
Når alt det er sagt, Dans forslag
er den bedre måde at udføre datosammenligninger på. Det paradigme
er mere indeksvenlig og virker uanset om din målkolonne indeholder en dato (kun) eller en dato og et klokkeslæt. Bemærk brugen af cf_sql_date
i hans eksempel.
cf_sql_timestamp
- sender både dato og klokkeslætcf_sql_date
- sender kun en dato. tidsværdien afkortes