Coldfusion CFQUERY с внутренним соединением и форматом даты не работает

Я пытаюсь разобраться с соединениями, mysql и coldfusion. Следующий запрос работает без последнего условия.

        <cfquery name="GetWeekends">
        SELECT w.id, w.weekend_type, w.community_id, w.start_date, w.end_date,
          w.language,
          c.community_id, c.location, c.language, c.state, c.country
        FROM _weekends w
        INNER JOIN _communities c
        ON w.community_id=c.community_id
        WHERE w.weekend_type = 1 AND w.start_date > Now() AND           
        #DateFormat(w.start_date, "m")# = '#form.home_by_month#'
        ORDER BY w.start_date ASC
        </cfquery>

Он умирает на

  #DateFormat(w.start_date, "m")#

говорит мне, что переменная [W] не существует. Извините, я учусь, пока хожу сюда...


person mck    schedule 31.08.2016    source источник
comment
Под «умиранием» означает ли это, что он приходит с ошибкой?   -  person Sterling Archer    schedule 31.08.2016
comment
Да, переменная [W] не существует   -  person mck    schedule 31.08.2016
comment
Кроме того, я настоятельно рекомендую использовать параметр cfquery для очистки вашей переменной. Я почти уверен, что вам не нужны осьминожки внутри тега запроса, но прошло больше года с тех пор, как я работал с cfquery.   -  person Sterling Archer    schedule 31.08.2016
comment
Ах, я не думаю, что вы можете применить не SQL-функцию к такому запросу.   -  person Sterling Archer    schedule 31.08.2016
comment
Мне нужно получить месяц (т.е. 1,2,3,4,5,6,7,8,9,10,11 или 12) из ​​w.start_date, который хранится в MySQL как DATE - и сравните это с тем, что я передаю в #form.home_by_month#   -  person mck    schedule 31.08.2016
comment
Я знаю, что это вопрос PHP, stackoverflow.com/questions/2039839/, но я думаю, что вы ищете функцию MYSQL MONTH()   -  person Sterling Archer    schedule 31.08.2016
comment
Это сделало это! Большое спасибо. Учимся Учим Учим!   -  person mck    schedule 31.08.2016


Ответы (3)


Проблема здесь в том, что DateFormat() — это функция ColdFusion, и ее нельзя применять с «переменной» MySQL (w). Вам нужно использовать функцию MONTH() для MySQL и передать в нее дату.

Не забудьте дезинфицировать входные данные формы, вы очень восприимчивы к SQL-инъекциям. Используйте cfqueryparam следующим образом:

MONTH(w.start_date) = <cfqueryparam cfsqltype="cf_sql_integer" value="#form.home_by_month#" />
person Sterling Archer    schedule 31.08.2016

(Слишком долго для комментариев...)

Поскольку вы упомянули, что являетесь новичком в CF, небольшой справочный материал о том, как CF обрабатывает запросы к базе данных, может помочь понять, почему произошла ошибка и какие типы действий вы можете (и не можете) делать в cfquery.

Хотя CF может взаимодействовать с механизмом базы данных, они совершенно разные и говорят на совершенно разных языках. Тот факт, что вы можете смешивать CFML и SQL в теге cfquery, создает ложное впечатление, что функции CF могут работать с объектами базы данных (или наоборот). Они не могут. Сервер CF ничего не знает об объектах базы данных (и ядро ​​базы данных не понимает CFML). Любой код CFML в теге запроса обрабатывается сначала — на сервере CF. Затем сгенерированный SQL отправляется в механизм базы данных и выполняется отдельно.

Когда сервер CF встречает запрос к базе данных, он анализирует содержимое тега, ища переменные или выражения CFML, которые должны быть оценены, т. е.:

SELECT Column FROM Table WHERE ColA = '#form.someField#' AND ColB = '#form.otherField#'

Затем он преобразует эти переменные и выражения в буквальные значения, т.е. строки, числа и т.д. Наконец, CF передает сгенерированную строку SQL механизму базы данных для выполнения, т.е.:

SELECT Column FROM Table WHERE ColA = 'John Smith' AND ColB = 'ABC'

Таким образом, причина, по которой CF задыхается от #DateFormat(w.start_date, "m")#, заключается в том, что он не понимает, что w.start_date относится к столбцу базы данных. Он считает, что это имя переменной CF: в частности, структуры с именем «w», содержащей ключ «start_date». Очевидно, что таких переменных не существует. Отсюда и неопределенная ошибка.

person Leigh    schedule 01.09.2016
comment
Это очень хорошее объяснение того, как языковые переменные и переменные базы данных сосуществуют в запросе. (Также, привет Ли!) - person Sterling Archer; 01.09.2016
comment
Спасибо, Стерлинг. В некоторых отношениях это аналогично смешиванию клиентского (JS) и серверного кода (CF) в одном скрипте. То, что вы можете смешивать их, не означает, что сервер CF может выполнять код на стороне клиента или наоборот ;-) - person Leigh; 01.09.2016

Рабочее решение было благодаря Sterling Archer:

<cfquery name="GetWeekends">
    SELECT w.id
           , w.weekend_type
           , w.community_id
           , w.start_date
           , w.end_date
           , w.language
           , c.community_id
           , c.location
           , c.language
           , c.state
           , c.country
    FROM   _weekends w INNER JOIN _communities c ON w.community_id = c.community_id
    WHERE w.weekend_type = 1 
    AND   w.start_date > Now() 
    AND   MONTH(w.start_date) = '#form.home_by_month#'
    ORDER BY w.start_date ASC
</cfquery>
person mck    schedule 31.08.2016
comment
Если это ваше решение, вы должны последовать совету Стерлинга также использовать cfqueryparam. Всегда используйте cfqueryparam при отправке параметров в запросе к базе данных. - person beloitdavisja; 01.09.2016
comment
Кроме того, фильтрация по месяцу, а не по году может привести к неожиданным результатам. - person Dan Bracuk; 01.09.2016
comment
Кроме того, если вы ищете записи для определенного месяца и года, рассмотрите возможность использования эта парадигма более гибкая, не говоря уже о дружественности к индексам, чем использование Month(). - person Leigh; 01.09.2016
comment
Дэн, конечно. В случае этого запроса я действительно ищу результаты за определенный месяц, независимо от года. - person mck; 02.09.2016
comment
(Изменить) @mck - Да, если вы ищете конкретный месяц (для любого года в будущем), то это законное использование месяца (). Кстати, не уверен, что это уместно в данном случае, но имейте в виду, что now() включает в себя и дату, и время. Таким образом, при сравнении будут исключены записи, имеющие одинаковую дату, но более раннее время. - person Leigh; 02.09.2016