запросы с нулями и списками

У меня есть

QueryExecute(

    SELECT *
    FROM dbo.pages
    WHERE ID IN ( :id )
    ...
   ,
   {
       id : { value = rc.id, cfsqltype : "cf_sql_integer, list : true }
   }

Почти всегда это работает. Дело в том, что rc.id может быть пустым. Если он пуст, то все идентификаторы должны совпадать. Я застрял в том, как это сделать


person James A Mohler    schedule 29.08.2019    source источник
comment
Чтобы было ясно... Это то, что вам нужно? stackoverflow.com/questions/19357990/   -  person TRose    schedule 29.08.2019
comment
(Изменить) Это невозможно только с одним предложением IN. Я считаю, что самый чистый способ - построить оператор sql условно, т.е. добавить это условие к предложению where, только если параметр не пуст. Подход or, упомянутый в ссылке, действительно работает, но для этого потребуется более сложный код + sql, который менее читаем IMO.   -  person SOS    schedule 29.08.2019
comment
@TRose очень похоже, но с IN   -  person James A Mohler    schedule 29.08.2019
comment
Если вы хотите написать это таким образом, это требует двух условий. Первое является текущим предложением IN, а второе должно возвращать true, когда переменная пуста. Например where ( column IN ( :idList ) OR :copyIDList = '' ) ... more .   -  person SOS    schedule 29.08.2019


Ответы (2)


Здесь есть два разных варианта.

1) Вы можете манипулировать строкой запроса, чтобы включить оператор IN только в том случае, если переменная не пуста.

То, как вы это сделаете, действительно зависит от остальной части запроса и от того, как вы хотели бы это сделать.

<cfset sqlstr = "SELECT * FROM dbo.pages" />
<cfif len(rc.id)>
    <cfset sqlstr &= " WHERE ID IN ( :id )" />
</cfif>

Вы могли бы создавать более чисто с условным выводом...

WHERE #len(rc.id) ? "ID IN ( :id )" : ""#

Чтобы не беспокоиться о включении WHERE/AND/OR, один небольшой трюк заключается в включении предложения, которое всегда будет проходить (или никогда в случае ORing).

WHERE 1=1 
    #len(rc.id) ? "AND ID IN ( :id )" : ""#
    AND ...

2) Дважды передать параметр и выполнить проверку в базе данных

SELECT *
FROM dbo.pages
WHERE (len(':id') = 0 OR ID IN ( :id ))
...

-- note: this may be problematic if CF is passing null when blank

или просто длина

    QueryExecute(

    SELECT *
    FROM dbo.pages
    WHERE (:idlen > 0 OR ID IN ( :id ))
    ...
   ,
   {
       id : { value = rc.id, cfsqltype : "cf_sql_integer, list : true },
       idlen : { value = len(rc.id), cfsqltype : "cf_sql_integer" }
   }
person Dan Roberts    schedule 29.08.2019
comment
включите предложение, которое всегда будет проходить ... или, если в предложении есть дополнительные условия (похоже, что они есть), которые всегда должны быть включены, просто переместите их в начало предложения where. - person SOS; 29.08.2019
comment
@Ageax да, хорошая мысль. Имелась в виду эта подсказка для более сложных случаев :) - person Dan Roberts; 29.08.2019
comment
Ага. Тем не менее, полезно знать, если все условия являются необязательными. - person SOS; 30.08.2019
comment
@DanRoberts Хотя ваше условие len(rc.id) соответствует ложному, в этот раз проблема возникнет в частях queryParam. Потому что вы проверили условие только в разделах WHERE, а не в разделе queryParam. Поэтому я надеюсь, что вам придется проверить те же условия и в queryparam. - person Kannan.P; 30.08.2019

Здесь я также привел пример кода для создания условного параметра queryparam. Для целей тестирования я создал некоторые параметры и значения по умолчанию.

<cfparam name="id" default="1,2,3,4,5,6">

Установите детали запроса в виде строки и сохраните ее в другой переменной, как упомянуто выше @danRoberts.

<cfset MyQry = "SELECT * FROM pages ">

Убедитесь, что значение rc.id пустое. Если это не так, добавьте предложение IN.

<cfif len(rc.id) >
    <cfset MyQry &= " WHERE id IN ( :id ) ">
</cfif>

Для справки, я также добавил несколько дополнительных операторов.

<cfset MyQry &= " limit 10 "> 

Затем создайте новый запрос на основе оператора new.

<cfset qry = new Query( datasource ='yourDataSource' , sql = MyQry) >

После этого добавьте queryParam для :ID, если rc.id не пуст.

<cfif len(rc.id) >
<cfset qry.addParam( name="id", value="#rc.id#",cfsqltype="cf_sql_varchar",list='true') >
</cfif>

Примечание. При использовании INoperator вы должны установить list='true' для параметра queryParam.

Затем вы выполняете запрос, как показано ниже

<cfset Result = qry.execute().getResult() >
<cfdump var="#Result#" />

Предложение WHERE с queryParam будет выполняться только тогда, когда rc.ID содержит значение.

person Kannan.P    schedule 30.08.2019
comment
Мне не нравится идея переноса формы QueryExecute в new Query. - person James A Mohler; 30.08.2019