ColdFusion 动态 SQL 与 cfif
ColdFusion Dynamic SQL with cfif
我正在尝试编写一个查询,该查询将接受从另一个页面传递的 4 个可能参数中的一个。用户将 select 这些参数之一进行搜索,然后查询将根据传递的参数评估其中哪些 selected。我正在尝试使用 cfif 来完成此操作,但我一定遗漏了一些东西。也许是 cfelse,或者,也许我离题了。这会比 cffunction 更好吗?我收到错误 "variable 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>
我想到了两个选项:您可以让它像包含一样工作,也可以像函数一样调用它。
独立包含(不太常见)
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>
标签隔离了它的内容,这意味着 your_query.cfm
内的变量(分配给 caller
范围的变量除外)对调用模板是可见的(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. --->
这应该让您了解您可以实现什么。
我会查看变量范围并检查以确保变量存在。那么,让我们看看你的条件之一。
<cfif StructKeyExists(url,"DivisionCode") AND url.DivisionCode NEQ "false">
AND DivisionCode = <cfqueryparam value="#url.DivisionCode#" cfsqltype="cf_sql_varchar">
</cfif>
在 "DivisionCode" 之前添加 "url." 前缀将指定您要查找变量的范围。这并不能真正帮助直接解决您的问题,但会让您的代码更清晰一些,错误消息也更有用。
添加 StructKeyExists() 检查以确保该变量首先在 URL 中可用。根据您编写代码的方式,我猜您不想按未包含的 URL 变量进行过滤,因此可以解决这个问题。
只要在每个 cfif 上做同样的事情,你就会像雨一样正确。
我正在尝试编写一个查询,该查询将接受从另一个页面传递的 4 个可能参数中的一个。用户将 select 这些参数之一进行搜索,然后查询将根据传递的参数评估其中哪些 selected。我正在尝试使用 cfif 来完成此操作,但我一定遗漏了一些东西。也许是 cfelse,或者,也许我离题了。这会比 cffunction 更好吗?我收到错误 "variable 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>
我想到了两个选项:您可以让它像包含一样工作,也可以像函数一样调用它。
独立包含(不太常见)
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>
标签隔离了它的内容,这意味着 your_query.cfm
内的变量(分配给 caller
范围的变量除外)对调用模板是可见的(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. --->
这应该让您了解您可以实现什么。
我会查看变量范围并检查以确保变量存在。那么,让我们看看你的条件之一。
<cfif StructKeyExists(url,"DivisionCode") AND url.DivisionCode NEQ "false">
AND DivisionCode = <cfqueryparam value="#url.DivisionCode#" cfsqltype="cf_sql_varchar">
</cfif>
在 "DivisionCode" 之前添加 "url." 前缀将指定您要查找变量的范围。这并不能真正帮助直接解决您的问题,但会让您的代码更清晰一些,错误消息也更有用。
添加 StructKeyExists() 检查以确保该变量首先在 URL 中可用。根据您编写代码的方式,我猜您不想按未包含的 URL 变量进行过滤,因此可以解决这个问题。
只要在每个 cfif 上做同样的事情,你就会像雨一样正确。