Ignorování správného přístupu
na chvíli se to stane důvodem, že používáte nesprávný cfsqltype
pro parametry. Takže ve skutečnosti posíláte do databáze jiné hodnoty (a následně provádíte jiné srovnání), než si myslíte. Výsledkem je, že dotaz nenajde žádné odpovídající záznamy. Proto je váš graf prázdný.
Pomocí cf_sql_timestamp
převádíte "hodnotu" na úplný objekt data/času. Nicméně YEAR() vrátí pouze čtyřmístné číslo. Takže srovnáváte jablka a pomeranče. Koncepčně váš dotaz ve skutečnosti dělá toto:
WHERE 2014 = {ts '2009-02-13 23:31:30'}
Důvod, proč nevyvolá chybu, je ten, že hodnoty data/času jsou interně uloženy jako čísla. Takže vlastně porovnáváte malé číslo (tj. rok) s opravdu velkým číslem (tj. datum/čas). Je zřejmé, že hodnota data bude mnohem větší, takže téměř nikdy nebude odpovídat číslu roku. Opět koncepčně váš dotaz dělá toto:
WHERE 2014 = 1234567890
Protože cfsqltype je volitelný, mnoho lidí si myslí, že to není příliš důležité – ale je.
-
Ověření: Kromě dalších výhod cfqueryparam ověřuje dodanou „hodnotu“ na základě
cfsqltype
(datum, datum a čas, číslo atd.). K tomu dochází před sql je vždy odeslán do databáze. Pokud je tedy vstup neplatný, neztrácíte volání databáze. Pokud vynecháte cfsqltype, nebo jen použijete výchozí ie řetězec, pak toto dodatečné ověření ztratíte. -
Přesnost Výběr správného cfsqltype zajistí odeslání správné hodnoty do databáze. Jak bylo ukázáno výše, použití nesprávného typu může způsobit, že CF odešle nesprávnou hodnotu do databáze.
cfsqltype
také zajišťuje, že hodnoty jsou odesílány do databáze v nejednoznačném formátu, databáze bude interpretovat tak, jak očekáváte. Technicky můžete vše odeslat do databáze jako řetězec. To však nutí databázi provést implicitní konverzi (obvykle nežádoucí).Při implicitní konverzi je interpretace řetězců ponechána zcela na databázi – a ta nemusí vždy přinést odpověď, kterou byste očekávali. Odeslání data jako řetězců, spíše než datových objektů, je toho ukázkovým příkladem. Jak bude aktuální databáze interpretovat řetězec data jako „05/04/2014“? Jako 5. dubna nebo 4. května? Záleží. Změňte databázi nebo nastavení databáze a výsledek může být úplně jiný.
Jediným způsobem, jak zajistit konzistentní výsledky, je zadat vhodný typ cfsql. Měl by odpovídat datovému typu porovnávacího sloupce/funkce nebo alespoň ekvivalentnímu typu. V případě YEAR()
, vrátí čtyřmístné číslo. Měli byste tedy použít cf_sql_integer
, jak Adrian zmínil komentáře
. Totéž platí pro váš MONTH() srovnání.
WHERE Year(ColumnName) = <cfqueryparam value="2014" cfsqltye="CF_SQL_INTEGER">
AND Month(ColumnName) = <cfqueryparam value="11" cfsqltye="CF_SQL_INTEGER">
Když jsem to všechno řekl, Danův návrh
je lepší způsob, jak provádět srovnání dat. Toto paradigma
je přátelštější k indexům a funguje bez ohledu na to, zda váš cílový sloupec obsahuje datum (pouze) nebo datum a čas. Všimněte si použití cf_sql_date
v jeho příkladu.
cf_sql_timestamp
- odešle datum i čascf_sql_date
- posílá pouze datum. hodnota času je zkrácena