使用cfif的ColdFusion动态SQL

时间:2017-12-08 01:53:22

标签: coldfusion

我正在尝试编写一个查询,该查询将接受从另一个页面传递的4个可能参数中的一个。用户将选择这些参数中的一个进行搜索,然后查询将根据传递的参数评估选择了哪些参数。我试图使用cfif来实现这一目标但我必须遗漏一些东西。也许是一个cfelse,和OR,或者我可能已经离开了。这会像cffunction一样好吗?我得到一个错误"变量DivisionCode"未定义。谢谢。

<cfquery name="Summary" datasource="dsn">
    SELECT
        *
    FROM
        disposal
    WHERE 1=1

    <cfif DivisionCode NEQ "false">
    AND DivisionCode = <cfqueryparam value="#url.DivisionCode#" 
   cfsqltype="cf_sql_varchar">
   </cfif>
   <cfif DistrictCode NEQ "false">
    AND DistrictCode = <cfqueryparam value="#url.DistrictCode#" 
   cfsqltype="cf_sql_varchar">
   </cfif>
   <cfif SiteCode NEQ "false">
    AND SiteCode = <cfqueryparam value="#url.SiteCode#" 
   cfsqltype="cf_sql_varchar">
  </cfif>
  <cfif RegionCode NEQ "false">
    AND RegionCode = <cfqueryparam value="#url.RegionCode#" 
  cfsqltype="cf_sql_varchar">
  </cfif>
  ORDER By
    CYear DESC
  </cfquery>

2 个答案:

答案 0 :(得分:6)

我会查看变量范围和检查以确保变量存在。所以,让我们看看你的一个条件。

<cfif StructKeyExists(url,"DivisionCode") AND url.DivisionCode NEQ "false">
   AND DivisionCode = <cfqueryparam value="#url.DivisionCode#" cfsqltype="cf_sql_varchar">
 </cfif>

添加“网址”。 “DivisionCode”之前的前缀将指定您查找变量的范围。这不会直接帮助您解决问题,但它会使您的代码更清晰,错误消息会更有帮助。

添加StructKeyExists()检查以确保该变量在URL中可用。根据你编写代码的方式,我猜你不想按照未包含的URL变量进行过滤,这样就可以解决这个问题。

在每个cfif上做同样的事情,你应该像雨一样正确。

答案 1 :(得分:4)

我想到了两个选项:您可以使其像包含一样工作,也可以将其称为函数。

隔离包括(不太常见)

your_query.cfm

<!--- declaring possible incoming parameters --->
<cfparam name="attributes.datasource"   type="string" default="dsn">
<cfparam name="attributes.divisionCode" type="string" default="">
<cfparam name="attributes.districtCode" type="string" default="">
<cfparam name="attributes.siteCode"     type="string" default="">
<cfparam name="attributes.regionCode"   type="string" default="">

<!--- declaring outgoing variable --->
<cfparam name="attributes.variable"     type="string" default="your_query">

<!--- retrieve result --->
<cfquery name="Summary" datasource="#attributes.datasource#">
    SELECT
        *
    FROM
        disposal
    WHERE 1=1

    <cfif len(attributes.divisionCode) gt 0>
        AND DivisionCode = <cfqueryparam value="#attributes.divisionCode#" cfsqltype="cf_sql_varchar">
    </cfif>
    <cfif len(attributes.districtCode) gt 0>
        AND DistrictCode = <cfqueryparam value="#attributes.districtCode#" cfsqltype="cf_sql_varchar">
    </cfif>
    <cfif len(attributes.siteCode) gt 0>
        AND SiteCode = <cfqueryparam value="#attributes.siteCode#" cfsqltype="cf_sql_varchar">
    </cfif>
    <cfif len(attributes.regionCode) gt 0>
        AND RegionCode = <cfqueryparam value="#attributes.regionCode#" cfsqltype="cf_sql_varchar">
    </cfif>

    ORDER BY
        CYear DESC
</cfquery>

<!--- set outgoing variable --->
<cfset caller[attributes.variable] = Summary>

invoking.cfm

<cfmodule divisionCode="foo" regionCode="bar" variable="my_query" template="your_query.cfm">
<cfdump var="#my_query#">

<!--- or --->

<cfset params = {}>
<cfset params.siteCode = "bla">
<cfif structKeyExists(url, "regionCode")>
    <cfset params.regionCode = url.regionCode>
</cfif>

<cfmodule attributeCollection="#params#" template="your_query.cfm">
<cfdump var="#your_query#">

<!--- etc. --->

<cfmodule>标记隔离了其内容,这意味着调用模板(calleryour_query.cfm内没有变量(invoking.cfm范围内的变量除外) })。这种方法基本上就像<cfhttp><cffile>这样的原生CF标记。

功能(更常见)

<cffunction name="yourQuery" access="public" output="false" returnType="query">

    <!--- declaring possible incoming parameters --->
    <cfargument name="datasource"   type="string" default="dsn">
    <cfargument name="divisionCode" type="string" default="">
    <cfargument name="districtCode" type="string" default="">
    <cfargument name="siteCode"     type="string" default="">
    <cfargument name="regionCode"   type="string" default="">

    <!--- retrieve result (the local. scope makes the variable exist in this function only) --->
    <cfquery name="local.Summary" datasource="#arguments.datasource#">
        SELECT
            *
        FROM
            disposal
        WHERE 1=1

        <cfif len(arguments.divisionCode) gt 0>
            AND DivisionCode = <cfqueryparam value="#arguments.divisionCode#" cfsqltype="cf_sql_varchar">
        </cfif>
        <cfif len(arguments.districtCode) gt 0>
            AND DistrictCode = <cfqueryparam value="#arguments.districtCode#" cfsqltype="cf_sql_varchar">
        </cfif>
        <cfif len(arguments.siteCode) gt 0>
            AND SiteCode = <cfqueryparam value="#arguments.siteCode#" cfsqltype="cf_sql_varchar">
        </cfif>
        <cfif len(arguments.regionCode) gt 0>
            AND RegionCode = <cfqueryparam value="#arguments.regionCode#" cfsqltype="cf_sql_varchar">
        </cfif>

        ORDER BY
            CYear DESC
    </cfquery>

    <!--- return result --->
    <cfreturn local.Summary>
</cffunction>

invoking.cfm

<cfset my_query = yourQuery("dsn", "foo", "", "bar")>
<cfdump var="#my_query#">

<!--- or --->

<cfset your_query = yourQuery(
    datasource: "dsn",
    siteCode: "bla"
    regionCode: ( structKeyExists(url, "regionCode") ? url.regionCode : "" )
)>
<cfdump var="#your_query#">

<!--- etc. --->

这应该让你了解你可以实现的目标。