2014-11-20 3 views
1

У меня есть запрос, который я бег, чтобы заполнить CFChart, что я пытаюсь параметризую:ColdFusion Параметрирования Запрос

<cfquery name="total" datasource="#datasource#"> 
    SELECT * 
    FROM closed_tickets 
    WHERE MONTH(closed_date) = #month# 
    AND YEAR(closed_date) = #dateFormat(theMonth,"yyyy")# 
    AND technician_id = #techID# 
</cfquery> 

Вот что я пробовал:

<!---Open tickets from chosen year where technician is active ---> 
<cfquery name="total" datasource="#datasource#">   
    SELECT * 
    FROM closed_tickets 
    WHERE MONTH(closed_date) = <CFQUERYPARAM Value="#month#"> 
    AND YEAR(closed_date) = #dateFormat(theMonth,"yyyy")#" cfsqltype="CF_SQL_TIMESTAMP"> 
    AND technician_id = <CFQUERYPARAM Value="#techID#"> 
</cfquery> 

Когда я изменить мой запрос к этому, это как-то ломает мой CFChart. У меня нет CFErrors на экране, но мой CFChart пуст.

Я свел к тому, связанным с этим в моем запросе:

#dateFormat(theMonth,"yyyy")#" cfsqltype="CF_SQL_TIMESTAMP" 

Когда я удалить эту параметризованную часть запроса и просто поставить

#dateFormat(theMonth,"yyyy")# 

это работает.

Может ли кто-нибудь пролить свет на это?

ответ

4

У меня нет CFErrors на экране, но мой CFChart пуст.

Игнорирование correct approach на мгновение, причина того, что происходит в том, что вы используете неправильный cfsqltype для параметров. Таким образом, вы фактически отправляете разные значения в базу данных (и, следовательно, выполняете другое сравнение), чем вы думаете. В результате запрос не находит подходящие записи. Вот почему ваш график пуст.

Используя cf_sql_timestamp, вы преобразовываете «значение» в полный объект даты/времени. Однако YEAR() возвращает только четырехзначное число. Итак, вы сравниваете яблоки и апельсины. Концептуально, ваш запрос на самом деле делает это:

WHERE 2014 = {ts '2009-02-13 23:31:30'} 

Причина не выдаст ошибку в том, что дата/время значения сохраняются как числа внутренне. Таким образом, вы фактически сравниваете небольшое число (т.е. год) с действительно большим числом (т.е. датой/временем). Очевидно, что значение даты будет намного больше, поэтому почти никогда не будет соответствовать номеру года.Опять же, концептуально ваш запрос делает это:

WHERE 2014 = 1234567890 

Поскольку cfsqltype не является обязательным, многие люди думают, что это не очень важно - но она есть.

  • Validation: В дополнение к другим его преимуществ, cfqueryparam проверяет входящий в комплект поставки «значение», на основе cfsqltype (дата, дата и время, номер, и так далее). Это происходит до sql всегда отправляется в базу данных. Поэтому, если вход недействителен, вы не тратите время на вызов базы данных. Если вы опускаете cfsqltype или просто используете строку, указанную по умолчанию, то вы теряете эту дополнительную проверку.

  • Точность Выбор правильного cfsqltype гарантирует, что вы отправите правильное значение в базу данных. Как показано выше, использование неправильного типа может привести к тому, что CF отправит неправильное значение в базу данных.

    cfsqltype также гарантирует, что значения передаются в базу данных в недвусмысленном формате, и база данных будет интерпретировать то, как вы ожидаете. Технически вы можете отправить все в базу данных строку. Однако это заставляет базу данных выполнять implicit conversion (обычно нежелательно).

    С неявным преобразованием интерпретация строк остается полностью до базы данных - и это может не всегда соответствовать ответу, который вы ожидаете. Ярким примером этого является представление дат как строк, а не объектов даты. Как текущая база данных будет интерпретировать строку даты типа «05/04/2014»? Как 5 апреля или 4 мая? Это зависит. Измените базу данных или настройки базы данных, и результат может быть совершенно другим.

Единственный способ обеспечить согласованные результаты - указать соответствующий тип cfsqltype. Он должен соответствовать типу данных столбца сравнения/функции или, по крайней мере, эквивалентного типа. В случае YEAR() он возвращает четырехзначное число. Поэтому вы должны использовать cf_sql_integer, как Adrian mentioned the comments. То же самое относится к вашему сравнению MONTH().

WHERE Year(ColumnName) = <cfqueryparam value="2014" cfsqltye="CF_SQL_INTEGER"> 
AND Month(ColumnName) = <cfqueryparam value="11" cfsqltye="CF_SQL_INTEGER"> 

Теперь, сказав все, что Dan's suggestion это лучший способ для выполнения сравнения дат. That paradigm более удобен для индексирования и работает независимо от того, содержит ли ваш целевой столбец дату (только) или дату и время. Обратите внимание на использование cf_sql_date в его примере.

  • cf_sql_timestamp - посылает и дату и время
  • cf_sql_date - отправляет только дату. значение времени усекается
+0

Спасибо за подробный ответ. Это очень помогает. –

+0

Добро пожаловать. Работа с датами и временем намного проще, если вы осознаете, что это сводится к простому сравнению чисел :) – Leigh

2

Ваш лучший выбор - это параметризовать каждую переменную, попавшую в ваш запрос.

Включите cfsqltype, а также значение.

<cfquery name="total" datasource="#datasource#">   
    select * 
    from closed_tickets 
    where MONTH(closed_date) = <cfqueryparam cfsqltype="cf_sql_integer" value="#month#"> 
      AND YEAR(closed_date) = <cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="#dateFormat(theMonth,"yyyy")#" > 
      AND technician_id = <cfqueryparam cfsqltype="cf_sql_integer" value="#techID#"> 
</cfquery> 

CF_SQL_VARCHAR может работать, и он не может, в зависимости от того, как дата на самом деле хранится (тип даты или вар символов).

+0

Учитывая, что запрос использует функции даты, данные, вероятно, хранятся как дата. –

3

Предлагаю вам изменить свой подход. Начните с

StartDate = CreateDate(TheYearYouWant, TheMonthYouWant, 1); 
EndDate = DateAdd("m", 1, StartDate); 

и дата фильтрации запроса становится:

where closed_date >= <cfqueryparam cfsqltype="cf_sql_date" value="#StartDate#"> 
and closed_date < <cfqueryparam cfsqltype="cf_sql_date" value="#EndDate#"> 

Это будет выполняться быстрее, чем при использовании функций в ИНЕКЕ.

+0

Плюс один для предотвращения функций. Я начал говорить то же самое, но ты избил меня. – Leigh

Смежные вопросы