Ignorando el enfoque correcto
por un momento, la razón por la que sucede es que está utilizando el cfsqltype
incorrecto para los parámetros. Entonces, en realidad está enviando valores diferentes a la base de datos (y, en consecuencia, realizando una comparación diferente) de lo que está pensando. Como resultado, la consulta no encuentra ningún registro coincidente. Es por eso que su gráfico está en blanco.
Usando cf_sql_timestamp
está convirtiendo el "valor" en un objeto de fecha/hora completa. Sin embargo, YEAR() solo devuelve un número de cuatro dígitos. Así que estás comparando manzanas y naranjas. Conceptualmente, su consulta en realidad está haciendo esto:
WHERE 2014 = {ts '2009-02-13 23:31:30'}
La razón por la que no arroja un error es que los valores de fecha/hora se almacenan como números internamente. Entonces, en realidad está comparando un número pequeño (es decir, un año) con un número realmente grande (es decir, fecha/hora). Obviamente, el valor de la fecha será mucho mayor, por lo que casi nunca coincidirá con el número del año. De nuevo, conceptualmente su consulta está haciendo esto:
WHERE 2014 = 1234567890
Dado que cfsqltype es opcional, mucha gente piensa que no es muy importante, pero lo es.
-
Validación: Además de sus otros beneficios, cfqueryparam valida el "valor" provisto, basado en el
cfsqltype
(fecha, fecha y hora, número, etcétera). Esto ocurre antes el sql se envía alguna vez a la base de datos. Entonces, si la entrada no es válida, no desperdicia una llamada a la base de datos. Si omite el tipo cfsql, o simplemente usa la cadena ie predeterminada, perderá esa validación adicional. -
Precisión Seleccionar el tipo de cfsql adecuado garantiza que envíe el valor correcto a la base de datos. Como se demostró anteriormente, usar el tipo incorrecto puede hacer que CF envíe el valor incorrecto a la base de datos.
El
cfsqltype
también garantiza que los valores se envíen a la base de datos en un formato no ambiguo que la base de datos interpretará de la manera esperada. Técnicamente, podría enviar todo a la base de datos como una cadena. Sin embargo, eso obliga a la base de datos a realizar conversión implícita (generalmente indeseable).Con la conversión implícita, la interpretación de las cadenas se deja completamente en manos de la base de datos, y es posible que no siempre obtenga la respuesta esperada. Enviar fechas como cadenas, en lugar de objetos de fecha, es un excelente ejemplo de eso. ¿Cómo interpretará la base de datos actual una cadena de fecha como "04/05/2014"? ¿Como un 5 de abril o un 4 de mayo? Depende. Cambie la base de datos o la configuración de la base de datos y el resultado puede ser completamente diferente.
La única forma de garantizar resultados consistentes es especificar el tipo de cfsql apropiado. Debe coincidir con el tipo de datos de la columna/función de comparación, o al menos con un tipo equivalente. En el caso de YEAR()
, devuelve un número de cuatro dígitos. Entonces deberías usar cf_sql_integer
, como Adrian mencionó los comentarios
. Lo mismo se aplica a su MONTH() comparación.
WHERE Year(ColumnName) = <cfqueryparam value="2014" cfsqltye="CF_SQL_INTEGER">
AND Month(ColumnName) = <cfqueryparam value="11" cfsqltye="CF_SQL_INTEGER">
Habiendo dicho todo eso, Sugerencia de Dan
es la mejor manera de realizar comparaciones de fechas. Ese paradigma
es más amigable con los índices y funciona independientemente de si su columna de destino contiene una fecha (solo) o una fecha y hora. Tenga en cuenta el uso de cf_sql_date
en su ejemplo.
cf_sql_timestamp
- envía tanto una fecha como una horacf_sql_date
- envía una fecha solamente. el valor de tiempo se trunca