使用在sql查询中调用列的方式返回查询行

时间:2015-07-11 06:36:34

标签: coldfusion

我有一个查询,我按照我想要的方式调用列,我不能使用查询的ColumnList,因为它按字母顺序排序列,另一件事我需要获取查询的特定行及其关联的列结构:

所以这是我的功能,我试图以我想要的方式带来列:

<cffunction name="rowToStruct" access="public" returntype="struct" output="false">
    <cfargument name="queryObj" type="query" required="true" />
    <cfargument name="row" type="numeric" required="true" />
    <cfset var returnStruct = structNew()>
    <cfset var colname = "">
    <cfset arguments.queryObj = arrayToList(arguments.queryObj.getMeta().getColumnLabels())>        
    <cfloop list="#arguments.queryObj#" index="colname">
      <cfset "returnStruct.#colname#" = arguments.queryObj[colname][arguments.row]>
    </cfloop>
    <cfreturn returnStruct/>
</cffunction>

在上述更改之前,函数如下所示:

<cffunction name="rowToStruct" access="public" returntype="struct" output="false">
    <cfargument name="queryObj" type="query" required="true" />
    <cfargument name="row" type="numeric" required="true" />

    <cfset var returnStruct = structNew()>
    <cfset var colname = "">

    <cfloop list="#arguments.queryObj.columnList#" index="colname">
      <cfset "returnStruct.#colname#" = arguments.queryObj[colname][arguments.row]>
    </cfloop>

    <cfreturn returnStruct/>
</cffunction>

我的一个人错误地给我一个错误:

您试图将类型为java.lang.String的标量变量取消引用为具有成员的结构。

2 个答案:

答案 0 :(得分:2)

getMetadata()函数按原始语句中定义的顺序返回列。文件:GetMetaData

我无法理解为什么您的代码会产生错误,尽管我这样做:

<cfset returnStruct[colname] = arguments.queryObj[colname][arguments.row]>

您是否可以使用屏幕上显示的确切错误更新您的问题,包括其关注的代码以及相关的行号(如果尚未启用,则切换强健例外处理)

答案 1 :(得分:2)

出错的原因是您要覆盖传递给函数的查询对象。新代码将arguments.queryObj的值重置为一个简单的字符串:

<cfset arguments.queryObj = arrayToList(arguments.queryObj.getMeta().getColumnLabels())> 

稍后在代码中,您尝试使用arguments.queryObj变量,就好像它仍然是查询对象一样。显然,这会导致错误,因为变量现在代表一个字符串:

  <cfset "returnStruct.#colname#" = arguments.queryObj[colname][arguments.row]>

解决方案是使用不同的变量来存储列名列表。由于它也是函数局部变量,因此请务必使用localvar正确定位。

也就是说,Adam mentioned in his answer,使用其中一个内置函数已经支持您需要的功能。因此,确实不需要使用coldfusion.sql.QueryTable查询类IMO的未记录方法。 GetMetaData(queryObject)返回包含两个键的结构数组:Name(列名),IsCaseSensitive(布尔值)。要遍历它,请使用&#34;数组&#34;循环而不是&#34;列表&#34;循环:

...
<cfset var returnStruct = {}>
<cfset var col = "">
<cfset var colArray = getMetaData(arguments.queryObj)>        
<cfloop array="#colArray#" index="col">
  <cfset returnStruct[col.Name] = arguments.queryObj[col.Name][arguments.row]>
</cfloop>
...

更新1:

  

我不能使用查询的ColumnList,因为它对列进行排序   alphabatically

这里更大的问题是CF结构没有订购。即使您按正确的顺序将值添加到结构中,也不会保留该顺序。您需要在调用代码中解决该问题(即使用GetMetaData(query))或让cffunction返回有序列名和行数据。后者似乎有点多余,但这完全取决于您在应用程序中使用该函数的方式。

更新2:

如果你真的需要一个排序结构..还有一些java类维护插入顺序,比如LinkedHashMap。由于它实现了java.util.Map,因此它可以是used like a CF structure(在大多数情况下)。

<cfset var returnStruct = createObject("java", "java.util.LinkedHashMap").init()>

Runnable Example on trycf.com

NB:虽然可以访问java对象,但是常见的错误是忘记了java是强类型的,与CF不同。如果您不了解它们,通常会subtle nuances that can easily bite you。所以请记住这一点......并确保阅读API。