Ignorer la approche correcte
pendant un moment, la raison qui se produit est que vous utilisez le mauvais cfsqltype
pour les paramètres. Ainsi, vous envoyez en fait des valeurs différentes à la base de données (et par conséquent, vous effectuez une comparaison différente) que vous ne le pensez. Par conséquent, la requête ne trouve aucun enregistrement correspondant. C'est pourquoi votre graphique est vide.
En utilisant cf_sql_timestamp
vous convertissez la "valeur" en un objet date/heure complet. Cependant, YEAR() ne renvoie qu'un nombre à quatre chiffres. Vous comparez donc des pommes et des oranges. Conceptuellement, votre requête fait ceci :
WHERE 2014 = {ts '2009-02-13 23:31:30'}
La raison pour laquelle il ne génère pas d'erreur est que les valeurs de date/heure sont stockées sous forme de nombres en interne. Donc, vous comparez en fait un petit nombre (c'est-à-dire l'année) à un très grand nombre (c'est-à-dire la date / l'heure). Évidemment, la valeur de la date sera beaucoup plus grande, donc elle ne correspondra presque jamais au numéro de l'année. Encore une fois, conceptuellement votre requête fait ceci :
WHERE 2014 = 1234567890
Étant donné que cfsqltype est facultatif, beaucoup de gens pensent que ce n'est pas très important - mais c'est le cas.
-
Validation : En plus de ses autres avantages, cfqueryparam valide la "valeur" fournie, basée sur le
cfsqltype
(date, date et heure, numéro, etc.). Cela se produit avant le sql est toujours envoyé à la base de données. Ainsi, si l'entrée n'est pas valide, vous ne perdez pas un appel à la base de données. Si vous omettez le cfsqltype, ou utilisez simplement la chaîne ie par défaut, vous perdez cette validation supplémentaire. -
Précision La sélection du bon cfsqltype garantit que vous envoyez la valeur correcte à la base de données. Comme démontré ci-dessus, l'utilisation du mauvais type peut amener CF à envoyer la mauvaise valeur à la base de données.
Le
cfsqltype
garantit également que les valeurs sont soumises à la base de données dans un format non ambigu que la base de données interprétera comme vous l'attendez. Techniquement, vous pouvez tout envoyer à la base de données par une chaîne. Cependant, cela force la base de données à effectuer une conversion implicite (généralement indésirable).Avec la conversion implicite, l'interprétation des chaînes est laissée entièrement à la base de données - et il se peut qu'elle ne fournisse pas toujours la réponse que vous attendez. La soumission de dates sous forme de chaînes, plutôt que d'objets de date, en est un excellent exemple. Comment la base de données actuelle interprétera-t-elle une chaîne de date telle que "05/04/2014" ? Comme un 5 avril ou un 4 mai ? Ça dépend. Modifiez la base de données ou les paramètres de la base de données et le résultat peut être complètement différent.
La seule façon d'assurer des résultats cohérents est de spécifier le cfsqltype approprié. Il doit correspondre au type de données de la colonne/fonction de comparaison, ou au moins à un type équivalent. Dans le cas de YEAR()
, il renvoie un nombre à quatre chiffres. Vous devez donc utiliser cf_sql_integer
, comme Adrian a mentionné les commentaires
. Il en va de même pour votre MOIS() comparaison.
WHERE Year(ColumnName) = <cfqueryparam value="2014" cfsqltye="CF_SQL_INTEGER">
AND Month(ColumnName) = <cfqueryparam value="11" cfsqltye="CF_SQL_INTEGER">
Après avoir dit tout cela, la suggestion de Dan
est la meilleure façon d'effectuer des comparaisons de dates. Ce paradigme
est plus convivial pour les index et fonctionne indépendamment du fait que votre colonne cible contienne une date (uniquement) ou une date et une heure. Notez l'utilisation de cf_sql_date
dans son exemple.
cf_sql_timestamp
- envoie à la fois une date et une heurecf_sql_date
- envoie une date seulement. la valeur de temps est tronquée