2015-07-11 101 views
1

我有一个查询,我像我想要的方式调用列,我无法使用查询的ColumnList,因为它按字母排序列,另一件事我需要获得查询的特定行,并在结构及其相关栏目:用SQL查询中调用列的方式返回查询行

因此,这里是我的功能,我试图把列的方式,我想:

<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

最后,返回的结构具有按字母顺序排列的键。那么,按照原始顺序获取列表会有什么用? – Beginner

回答

2

getMetadata()函数按照它们在原始语句中定义的顺序返回列。文档:GetMetaData

我不明白为什么你的代码会产生错误,但我会做到这一点:

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

你能有确切的错误更新你的问题,因为它在屏幕上显示,包括代码它重点关注以及相关的行号(如果不是已经开启了强制异常处理)

+0

这是因为他们用列名称列表覆盖查询变量。 – Leigh

+0

哦,对,是的。我只看第二个代码块。咄。 –

+0

实际上有一个更大的问题;-)因为他正在返回一个结构,订单不会保持无论如何(请参阅[我更新的答案](http://stackoverflow.com/a/31359765/104223))。 – Leigh

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,使用其中一个内置函数已经支持您需要的功能。所以没有必要使用查询类IMO的未公开方法。 GetMetaData(queryObject)返回包含两个键的结构数组:Name(列名),IsCaseSensitive(布尔值)。要遍历它,而不是使用一个“清单”,“阵列”循环圈:

... 
<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:

I cannot use ColumnList of query because it sorts the column 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。

+1

最后,返回的结构具有按字母顺序排列的键。那么,是否需要按原始顺序获取列表? – Beginner

+0

(编辑以保留线程上下文):@Beginner - 哈哈,我刚刚在发布时解决了这个问题。请参阅我的更新;-)请记住,可能有java类可以使用*,例如*可以维护排序顺序的CF结构。我个人认为这是过分的,但是...这是一个有效的选择。 – Leigh

+0

@Beginner - 小小的说明,并不是说结构按字母顺序返回键 - 它们只是没有*保证*顺序。 – Leigh