2

我有以下 ColdFusion 9 代码:

<cfloop from="1" to="#arrayLen(tagArray)#" index="i">
    <cfquery name="qryGetSPFAQs" datasource="#application.datasource#">
        EXEC searchFAQ '#tagArray[i]#'
    </cfquery>
</cfloop>

EXEC 在数据库服务器上执行一个存储过程,该过程返回数据行,具体取决于参数是什么。我想要做的是将查询组合成一个查询对象。换句话说,如果它循环 3 次并且每个循环返回 4 行,我想要一个在一个对象中包含所有 12 行的查询对象。我如何实现这一目标?

4

3 回答 3

2

您可能希望采用不同的方法(修改您的存储过程以接受多个参数或使用列表和fnSplit)并一次返回所有数据集。但是,要直接回答您的问题,您可以按照以下方式组合查询:

您可以在查询查询中使用 UNION 来组合所有数据集。

<cfloop from="1" to="#arrayLen(tagArray)#" index="i">
    <cfquery name="qryGetSPFAQs#i#" datasource="#application.datasource#">
        EXEC searchFAQ '#tagArray[i]#'
    </cfquery>
</cfloop>

<cfquery name="combined" dbtype="query">
    <cfloop from="1" to="#arrayLen(tagArray)#" index="i">
        select * from qryGetSPFAQs#i#
        <cfif i lt arrayLen(tagArray)>UNION</cfif>
    </cfloop>
</cfquery>
于 2010-05-28T21:09:20.390 回答
1

更直接的方法可能是这样的:

<cfset bigQ = queryNew("column")>
<cfloop from="1" to="#arrayLen(tagArray)#" index="i">
    <cfquery name="qryGetSPFAQs" datasource="#application.datasource#">
        EXEC searchFAQ '#tagArray[i]#'
    </cfquery>
    <cfset queryAddRow(bigQ)>
    <cfset querySetCell(bigQ, "column". qryGetSPFAQs)>
</cfloop>

您将需要为每一列分配一个 querySetCell()。查看实时文档中的查询功能以获取更多信息。

于 2010-05-28T23:37:13.810 回答
0

这是一个开箱即用的解决方案,将 StoredProc 放弃为 SQL 视图(我将解释)。

免责声明:没有看到 SP 源代码,我无法判断我的解决方案是否适合。我假设 SP 是相当基本的,并且我承认我通常更喜欢 SP 的编译执行而不是视图,但是 SQL 视图的一次性执行应该胜过 SP x 次的循环。

首先创建一个看起来像 SP 中的 SELECT 语句的视图(当然,减去参数化 - 您将在新视图的 CFQUERY 内的 WHERE 子句中介绍它。

其次,将您的循环设置为仅构建一个我们将用于 WHERE 子句的数据集。您需要使用 ArrayToList 和一些字符串操作来整理它,最终产品是存储在单个 CF 变量中的字符串,如下所示:

('ValueOfArrayElement1','ValueOfArrayElement2','Value_And_So_On')

构建字符串非常简单,使用 ArrayToList 的分隔符属性,循环完成后,将左括号和单引号附加到字符串的最左侧位置;并将单引号和右括号附加到字符串中最右边的位置。

现在,编写 CFQUERY 语句以从您的视图中选择您需要的列(而不是执行您的 SP)。而不是将参数传递给 SP,您将在 CFQUERY 中放置一个 WHERE 子句。

哦,顺便说一句,我说你需要一个 SQL 视图,但整个 SELECT可以在 CFQUERY 中构建。就个人而言,当我有一个多表 JOIN 时,我喜欢在 SQL 视图中定义它,它比 CFQUERY 中的 JOIN 执行得更快。最终,StoredProc 甚至更快,但是我们的 WHERE 子句对于这样的编码和阅读要友好得多,而不是在不循环进出 SQL 的情况下发送到 StoredProc。

如果可能的话,只访问一次数据库并返回是一个很好的目标。这就是为什么我们循环遍历数组以写入一个字符串,该字符串等于数据集中的所有值。这样,我们将只执行一次查询。

SELECT Col1, Col2, Col_etc
FROM SQL_View_Name
WHERE ColumnName in #BigStringWeMadeFromArrayToList#

当我们的 CFQUERY 被渲染时,该子句在 SQL 中看起来就像这样:

WHERE ColumnName in 
     ('ValueOfArrayElement1','ValueOfArrayElement2','Value_And_So_On')

所以你有它。就像我说的那样,这很好,因为它只访问数据库一次,而且由于我们正在构建一个视图,所以性能仍然非常好——比运行 StoredProc 4 次以上要好。(没有冒犯的意思)

我必须重复......没有看到SP代码,我不确定这是否可行。另外,为 SQL 视图(RDBMS 中的“较小”实体)放弃 StoredProc 有点奇怪,但我相信我们会获得更好的性能,而且我认为它也非常易读。

于 2010-09-25T04:31:48.173 回答