Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

ColdFusion parametrizando uma consulta


Ignorando a abordagem correta por um momento, a razão que acontece é que você está usando o cfsqltype incorreto para os parâmetros. Então você está realmente enviando valores diferentes para o banco de dados (e consequentemente realizando uma comparação diferente) do que você está pensando. Como resultado, a consulta não consegue localizar quaisquer registros correspondentes. É por isso que seu gráfico está em branco.

Usando cf_sql_timestamp você está convertendo o "valor" em um objeto de data/hora completo. No entanto, YEAR() retorna apenas um número de quatro dígitos. Então você está comparando maçãs e laranjas. Conceitualmente, sua consulta está realmente fazendo isso:
  WHERE  2014 = {ts '2009-02-13 23:31:30'}

A razão pela qual não gera um erro é que os valores de data/hora são armazenados como números internamente. Então você está realmente comparando um número pequeno (ou seja, ano) com um número realmente grande (ou seja, data/hora). Obviamente, o valor da data será muito maior, portanto, quase nunca corresponderá ao número do ano. Novamente, conceitualmente sua consulta está fazendo isso:
 WHERE 2014 = 1234567890

Como o cfsqltype é opcional, muitas pessoas pensam que não é muito importante - mas é.

  • Validação: Além de seus outros benefícios, cfqueryparam valida o "valor" fornecido, com base no cfsqltype (data, data e hora, número, etc.). Isso ocorre antes o sql é sempre enviado para o banco de dados. Portanto, se a entrada for inválida, você não desperdiçará uma chamada de banco de dados. Se você omitir o cfsqltype, ou apenas usar a string padrão, ou seja, você perderá essa validação extra.

  • Precisão Selecionar o cfsqltype adequado garante que você envie o valor correto para o banco de dados. Conforme demonstrado acima, usar o tipo errado pode fazer com que o CF envie o valor errado para o banco de dados.

    O cfsqltype também garante que os valores sejam enviados ao banco de dados em um formato não ambíguo que o banco de dados interpretará da maneira que você espera. Tecnicamente, você poderia enviar tudo para o banco de dados como uma string. No entanto, isso força o banco de dados a realizar uma conversão implícita (geralmente indesejável).

    Com a conversão implícita, a interpretação das strings é deixada inteiramente para o banco de dados - e pode nem sempre dar a resposta que você esperaria. O envio de datas como strings, em vez de objetos de data, é um excelente exemplo disso. Como o banco de dados atual interpretará uma string de data como "05/04/2014"? Como 5 de abril ou 4 de maio? Depende. Altere o banco de dados ou as configurações do banco de dados e o resultado pode ser completamente diferente.

A única maneira de garantir resultados consistentes é especificar o cfsqltype apropriado. Ele deve corresponder ao tipo de dados da coluna/função de comparação ou pelo menos um tipo equivalente. No caso de YEAR() , ele retorna um número de quatro dígitos. Então você deve usar cf_sql_integer , como Adrian mencionou os comentários . O mesmo se aplica ao seu MONTH() comparação.
 WHERE Year(ColumnName) = <cfqueryparam value="2014" cfsqltye="CF_SQL_INTEGER">
 AND   Month(ColumnName) = <cfqueryparam value="11" cfsqltye="CF_SQL_INTEGER"> 

Dito tudo isso, Sugestão de Dan é a melhor maneira de realizar comparações de datas. Esse paradigma é mais amigável ao índice e funciona independentemente de sua coluna de destino conter uma data (somente) ou uma data e hora. Observe o uso de cf_sql_date em seu exemplo.
  • cf_sql_timestamp - envia uma data e hora
  • cf_sql_date - envia apenas uma data. o valor do tempo está truncado