Ignorowanie właściwego podejścia
przez chwilę powodem tego jest to, że używasz nieprawidłowego cfsqltype
dla parametrów. Tak więc w rzeczywistości wysyłasz do bazy danych różne wartości (i w konsekwencji dokonujesz innego porównania) niż myślisz. W rezultacie zapytanie nie może znaleźć żadnych pasujących rekordów. Dlatego Twój wykres jest pusty.
Używając cf_sql_timestamp
konwertujesz „wartość” na pełny obiekt daty/godziny. Jednak ROK() zwraca tylko czterocyfrową liczbę. Więc porównujesz jabłka i pomarańcze. Koncepcyjnie Twoje zapytanie faktycznie działa tak:
WHERE 2014 = {ts '2009-02-13 23:31:30'}
Powodem, dla którego nie zgłasza błędu, jest to, że wartości daty/godziny są wewnętrznie przechowywane jako liczby. Tak więc w rzeczywistości porównujesz małą liczbę (tj. rok) z naprawdę dużą liczbą (tj. data/godzina). Oczywiście wartość daty będzie znacznie większa, więc prawie nigdy nie będzie pasować do numeru roku. Ponownie, koncepcyjnie Twoje zapytanie robi to:
WHERE 2014 = 1234567890
Ponieważ cfsqltype jest opcjonalny, wiele osób uważa, że nie jest to bardzo ważne - ale tak jest.
-
Weryfikacja: Oprócz innych korzyści, cfqueryparam sprawdza podaną "wartość" na podstawie
cfsqltype
(data, data i godzina, numer itp.). Dzieje się to przed sql jest zawsze wysyłane do bazy danych. Więc jeśli dane wejściowe są nieprawidłowe, nie marnujesz wywołania bazy danych. Jeśli pominiesz cfsqltype lub po prostu użyjesz domyślnego, tj. ciągu, stracisz tę dodatkową walidację. -
Dokładność Wybranie odpowiedniego cfsqltype zapewnia przesłanie prawidłowej wartości do bazy danych. Jak pokazano powyżej, użycie niewłaściwego typu może spowodować, że CF wyśle niewłaściwą wartość do bazy danych.
cfsqltype
zapewnia również, że wartości są przesyłane do bazy danych w jednoznacznym formacie, baza danych będzie interpretować w oczekiwany sposób. Technicznie rzecz biorąc, możesz wysłać wszystko do bazy danych jako ciąg znaków. Jednak zmusza to bazę danych do wykonania niejawnej konwersji (zwykle niepożądane).W przypadku konwersji niejawnej interpretacja ciągów jest całkowicie pozostawiona bazie danych — i może ona nie zawsze dać oczekiwaną odpowiedź. Przesyłanie dat jako ciągów, a nie obiektów dat, jest tego najlepszym przykładem. Jak bieżąca baza danych zinterpretuje ciąg daty, taki jak „05/04/2014”? Jak 5 kwietnia czy 4 maja? To zależy. Zmień bazę danych lub ustawienia bazy danych, a wynik może być zupełnie inny.
Jedynym sposobem na zapewnienie spójnych wyników jest określenie odpowiedniego cfsqltype. Powinien być zgodny z typem danych kolumny/funkcji porównania lub przynajmniej z równoważnym typem. W przypadku YEAR()
, zwraca czterocyfrową liczbę. Powinieneś więc użyć cf_sql_integer
, ponieważ Adrian wspomniał o komentarzach
. To samo dotyczy Twojego MONTH() porównanie.
WHERE Year(ColumnName) = <cfqueryparam value="2014" cfsqltye="CF_SQL_INTEGER">
AND Month(ColumnName) = <cfqueryparam value="11" cfsqltye="CF_SQL_INTEGER">
Powiedziawszy to wszystko, sugestia Dana
to lepszy sposób na porównanie dat. Ten paradygmat
jest bardziej przyjazny dla indeksów i działa niezależnie od tego, czy kolumna docelowa zawiera datę (tylko) czy datę i godzinę. Zwróć uwagę na użycie cf_sql_date
w jego przykładzie.
cf_sql_timestamp
- wysyła zarówno datę, jak i godzinęcf_sql_date
- wysyła tylko datę. wartość czasu jest obcinana