我可以在 ColdFusion 中按索引获取查询行吗?

Posted

技术标签:

【中文标题】我可以在 ColdFusion 中按索引获取查询行吗?【英文标题】:Can I get a query row by index in ColdFusion? 【发布时间】:2010-11-15 19:13:53 【问题描述】:

我想在 ColdFusion Query 对象中获取特定行而不循环它。

我想做这样的事情:

<cfquery name="QueryName" datasource="ds">
SELECT *
FROM    tablename
</cfquery>

<cfset x = QueryName[5]>

但是它给了我一个错误,说查询不能被“5”索引。我知道这个查询中有超过 5 条记录。

【问题讨论】:

CFLib.org 再次救援:cflib.org/udf/queryGetRow。那会让你做&lt;cfset x = queryGetRow(QueryName,5)&gt; 【参考方案1】:

你不能在 CF

<cfset x = QueryName.columnName[5]>

然而,自从我发布这个答案已经 8 年了。显然 CF11 终于实现了这个功能。见ugh StackExchange's answer。

【讨论】:

谢谢,这正是我要找的。​​span> 我更喜欢行和列的括号表示法,但任何一种方式都同样有效。查询名称[“列名称”][5]。例如,如果您想为列名使用变量,则需要括号表示法。 不正确。您可以获得一行,只是不使用标准的 CF API。而且您将无法通过变量名直接访问列——您必须知道索引。您可以执行 myquery.getRow(0) 来获取第一个“coldfusion.sql.imq.Row”,并执行 myrow.getColumn(0) 来获取第一列。 Row 也有一个方法来获取代表整行的 Object[]。 @Mark:是的,我认为大多数时候这对大多数人都没有帮助。这些是 java 对象/方法,对于日常使用来说不是那么方便:q=myQuery; r=q.getRow(3); rd=x.getRowData(); 或只是 rd=myQuery.getRow(3).getRowData(); 但这将返回一个 java-ish 值数组(您必须解析出 nulls/empties)你会失去你的列标题。我可以看到偶尔需要这样做,但通常会增加比您想要的更多的复杂性。【参考方案2】:

现在可以通过 QueryGetRow 在 Coldfusion 11 中完成此操作

<cfquery name="myQuery" result="myresult" datasource="artGallery" fetchclientinfo="yes" >
select * from art where ARTID >
<cfqueryparam value="2" cfsqltype="CF_SQL_INTEGER">
</cfquery>

<cfdump var="#myQuery#" >

<cfset data = QueryGetRow(myQuery, 1) >

<cfdump var="#data#" >

【讨论】:

杀手级答案。我很惭愧地说我不知道​​这个功能。 cf11 持续交付! @jyoseph 现在,如果他们能像 lucee 一样跟进,并在 cfquery 标记中添加 lazy="true",这样我就可以拉出数千行,而不必担心冷融合会耗尽所有内存。 请注意,QueryGetRow 将为空值返回 undefined,而 for(row in query) 循环将返回空字符串。 cf11 持续交付。【参考方案3】:

我认为有一个更简单的解决方案... 我猜你知道你的列名,只想要这个或那个。然后你不需要把整行放在一个结构中。您可以按行号引用查询(记住它基于 1 而不是 0)。

yourQueryName["yourColumnName"][rowNumber]

<cfoutput>
     #mycontacts["Name"][13]#
     #mycontacts["HomePhone"][13]# 
</cfoutput>

【讨论】:

【参考方案4】:

您必须先将查询转换为结构:

<cfscript>
    function GetQueryRow(query, rowNumber) 
        var i = 0;
        var rowData = StructNew();
        var cols = ListToArray(query.columnList);
        for (i = 1; i lte ArrayLen(cols); i = i + 1) 
            rowData[cols[i]] = query[cols[i]][rowNumber];
        
        return rowData;
    
</cfscript>

<cfoutput query="yourQuery">
    <cfset theCurrentRow = GetQueryRow(yourQuery, currentRow)>
    <cfdump var="#theCurrentRow#">
</cfoutput>

希望这会为您指明正确的方向。

【讨论】:

我认为这也是唯一的方法,直到我看到帕特里克的回答【参考方案5】:

我知道每当我用 Google 搜索“cfquery 括号表示法”时,我都会回到这个帖子。这是我编写的一个函数,用于使用括号表示法处理这种情况。希望这也可以帮助其他人:

<cffunction name="QueryGetRow" access="public" returntype="array" hint="I return the specified row's data as an array in the correct order">
    <cfargument name="query" required="true" type="query" hint="I am the query whose row data you want">
    <cfargument name="rowNumber" required="true" hint="This is the row number of the row whose data you want">

    <cfset returnArray = []>
    <cfset valueArray = []>

    <cfset cList = ListToArray(query.ColumnList)>
    <cfloop from="1" to="#ArrayLen(cList)#" index="i">
        <cfset row = query["#cList[i]#"][rowNumber]>
        <cfset row = REReplace(row, "(,)", " ")>
        <cfset returnArray[i] = row>
        <cfset i++>
    </cfloop>   
    <cfreturn returnArray>
</cffunction>

REReplace 是可选的,我把它放在里面用来清理逗号,这样以后如果你必须使用它就不会搞砸 arrayToList 函数。

【讨论】:

【参考方案6】:

我想从查询中提取一行,并保留列名(当然)。我就是这样解决的:

<cffunction name="getQueryRow" returntype="query" output="no">
    <cfargument name="qry" type="query" required="yes">
    <cfargument name="row" type="numeric" required="yes">
    <cfset arguments.qryRow=QueryNew(arguments.qry.columnlist)>
    <cfset QueryAddRow(arguments.qryRow)>
    <cfloop list="#arguments.qry.columnlist#" index="arguments.column">
        <cfset QuerySetCell(arguments.qryRow,arguments.column,Evaluate("arguments.qry.#arguments.column#[arguments.row]"))>
    </cfloop>
    <cfreturn arguments.qryRow>
</cffunction>

【讨论】:

谢谢!我不知道 cflib【参考方案7】:

前面介绍的通过列名和行号(variables.myquery["columnName"][rowNumber])获取查询数据的方法是正确的,但不方便获取整行查询数据。

我正在运行 Railo 4.1。这是一个很酷的解决方案。太糟糕了,这不能像我们想要的那样直接获得一整行数据,但是下面的方法可以让我们通过几个环节得到我们想要的。

当您serializeJSON(variables.myquery) 时,它会将查询更改为 JSON 格式的 cfml 结构对象,其中包含两项:“列”和“数据”。这两个都是数据数组。 “数据”数组是一个二维数组,先是行数据,然后是列数据。

问题是现在我们有一个不可用的字符串。然后,如果我们重新序列化它,它就不是查询,而是上述格式的可用常规结构。

假设我们已经有一个名为“variables.myquery”的查询变量。然后看下面的代码:

<cfset variables.myqueryobj = deserializeJSON(serializeJSON(variables.myquery)) />

现在你得到这个二维数组:

<cfset variables.allrowsarray = variables.myqueryobj.data />

你得到一个查询行数组:

<cfset variables.allrowsarray = variables.myqueryobj.data[1] />

以这种方式或最后一行:

<cfset variables.allrowsarray = variables.myqueryobj.data[variables.myquery.recordCount] />

并且您可以通过列序号迭代来获取各个列的值:

<cfset variables.allrowsarray = variables.myqueryobj.data[1][1] />

现在,对于大型查询结果,这可能会很慢并且可能不明智,但这仍然是一个很酷的解决方案。

【讨论】:

【参考方案8】:

查看queryGetRow 的文档。它接受一个查询对象和一个行的索引,第一行被引用的索引为1(非0)。这种方式使用的索引必须是一个正整数。

<cfquery name="QueryName" datasource="ds">
  SELECT *
  FROM tablename
</cfquery>

<!---
    This would retrieve the first record of the query
    and store the record in a struct format in the variable 'x'.
--->
<cfset x = queryGetRow(QueryName, 1) />
<!---
    This is an alternative using the member method form of queryGetRow
--->
<cfset x = QueryName.getRow(1) />

【讨论】:

我想知道为什么反对票。有两个版本的正确答案。成员函数方法很清楚。

以上是关于我可以在 ColdFusion 中按索引获取查询行吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 GROUP BY 中按行数获取前 N 行

如何使用 QueryDsl 在查询中按 id 删除重复行

在 MySQL 中按多列获取重复行

如何在freemarker模板中按索引获取列表项?

在javascript数组中按值获取索引

Access 2010 SQL--在交叉表查询中按聚合函数对行进行排序