【问题标题】:How to loop through stored procedure result in coldfusion如何循环遍历存储过程导致coldfusion
【发布时间】:2018-10-25 15:40:04
【问题描述】:

我想在 Coldfusion 中循环存储过程。我有下面的代码来循环查询。

<cfquery name="rates" dbtype="query">
        select code, rate
  from application.qry.currency
  where code = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.origCode#" />
     or code = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.toCode#" />
</cfquery>
<cfloop query="rates">
    <cfscript>
            if (code == arguments.origCode) origRate = rate;
            if (code == arguments.toCode) toRate = rate;
        </cfscript>
</cfloop>

现在查询被下面的存储过程替换了,我想做与上面代码相​​同的函数用于循环。在存储过程中,我确实有与上面相同的查询。先感谢您!

<cfstoredproc procedure="usp_get_rates" datasource="#variables.dsn#">
        <cfprocparam cfsqltype="cf_sql_varchar" dbvarname="@origCode" type="in" value="#arguments.origCode#"/>
        <cfprocparam cfsqltype="cf_sql_varchar" dbvarname="@toCode" type="in" value="#arguments.toCode#" />
</cfstoredproc>

上面的完整代码:

<cffunction name="convertCurrency" access="public" output="false" returntype="string">
  <cfargument name="amount" required="true" type="numeric" />
<cfargument name="origCode" required="true" type="string" />
<cfargument name="toCode" required="true" type="string" />
<cfscript>
        var theAmount = 0;
        var origRate = 0;
        var toRate = 0;
        var baseVal = 0;
        var newVal = 0;
        if (isNumeric(arguments.amount)) theAmount = arguments.amount;
        if (arguments.origCode == 'USD' && arguments.toCode == 'USD' || theAmount == 0) return theAmount;
        if (not isDefined("application.qry.currency")) initCurrencyRecordset();
    </cfscript>
<cfquery name="rates" dbtype="query">
        select code, rate
  from application.qry.currency
  where code = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.origCode#" />
     or code = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.toCode#" />
</cfquery>
<cfloop query="rates">
    <cfscript>
            if (code == arguments.origCode) origRate = rate;
            if (code == arguments.toCode) toRate = rate;
        </cfscript>
</cfloop>
<cfscript>
        if (origRate neq 0){
            baseVal = theAmount * (1 / origRate);
            newVal  = baseVal * toRate;
        }
        else {
            baseVal = theAmount * 1;
            newVal  = baseVal * toRate;
        }
        return newVal;
    </cfscript>

  <cffunction name="initCurrencyRecordset" access="private" output="false" returntype="void">
    <!--- <cfquery name="qry" datasource="#variables.dsn#">
        select distinct c.LOCAL_CUR as code, ISNULL(c.LocalConversionToUSD, c.x) as rate
        from SCS_FM.dbo.currency c
        join scs_fm.dbo.currency_code cc
            ON c.local_cur = cc.currency_code
        order by LOCAL_CUR
    </cfquery> --->

    <cfstoredproc procedure="usp_Rates_InitCurrencyRecordset_Qry" datasource="#variables.dsn#">
    <cfprocresult name="qry" >
    </cfstoredproc>

    <cflock scope="application" type="exclusive" timeout="20">
        <cfset application.qry.currency = duplicate(qry) />
    </cflock>
</cffunction>   

【问题讨论】:

  • 如果你从 cfquery 内部调用 store proc 并用它替换你的 sql stackoverflow.com/a/4136859/3254405
  • 你分享的代码是做什么的?它会抛出错误吗?它是否返回记录集?如果您转储结果&lt;cfdump var="#cfstoredproc#"&gt;,您会得到什么请在您的问题中包含这些详细信息。
  • 什么版本的 ColdFusion 和哪个 DBMS? dbvarname 在 6-10 中被忽略,但在 CF11 中恢复。但是如果你在循环中使用脚本,你不妨把整个东西放在脚本中,然后在里面循环。
  • @Shawn 我使用的是 CF11,而 dbms 是 sql server 2014。我应该在这一行给出的名称而不是 rate - .
  • if (not isDefined("application.qry.currency")) initCurrencyRecordset(); 表示您正在寻找缓存在application 范围内的查询对象。您可能应该将此查询对象传递到查询中,这样您就不会超出该函数来获取查询。此外,这似乎表明查询已经完成,因此您将无法转换为存储过程,除非您一直返回到application 中的查询。不能从存储过程中查询 CF 查询。

标签: sql sql-server coldfusion adobe


【解决方案1】:

根据到目前为止的详细信息,完成您的要求.....

我假设您的存储过程如下所示:

CREATE PROCEDURE dbo.usp_get_rates @origCode varchar(20), @toCode varchar(20)
AS  
BEGIN 
  SET NOCOUNT ON ;
  SELECT code, rate
  FROM dbo.currency
  WHERE code IN ( @origCode, @toCode )
END;  
GO  

注意:您希望将“dbo”替换为适合您的数据库架构。但是,如果您要跨数据库查询(请参阅上面关于 application.qry.currency 的评论),那么您将保持您的 FROM 调用相同,并将您的存储过程放置/引用到适当的架构中。

使用该过程,您的 ColdFusion 代码将如下所示:

<cfstoredproc procedure="usp_get_rates" datasource="#variables.dsn#">
        <cfprocparam cfsqltype="cf_sql_varchar" dbvarname="@origCode" type="in" value="#arguments.origCode#">
        <cfprocparam cfsqltype="cf_sql_varchar" dbvarname="@toCode" type="in" value="#arguments.toCode#">
        <cfprocresult name="rates">
</cfstoredproc>

<cfscript>
  // Initialize your variables. They won't exist if your query has 0 rows.
  var origRate = 0 ; // Or expected datatype
  var toRate   = 0 ; // Or expected datatype

  for (var thisrow in rates) {
     if ( thisrow.code == arguments.origCode ) { origRate = thisrow.rate ; }
     if ( thisrow.code == arguments.toCode) { toRate = thisrow.rate ; }
  }
</cfscript>

由于您使用的是arguments 范围,因此我假设此代码位于函数内部。这将允许您使用 var 关键字。

请注意,dbvarname 自 CFMX 以来已被忽略,并在 CF11 更新 3 中恢复。CF11 有一个 JVM 标志 (-Dcoldfusion.ignoredbvarname) 可以继续忽略 dbvarname,但该标志在 CF2016+ 中被忽略。

您可以使用简单的for 循环来遍历查询,但正如我上面所说,这可能不是您真正想要的。如果您的查询/存储过程返回多个结果,如果返回多个值,它将覆盖origRatetoRate。即如果您的查询有[{code:"x",rate:41},{code:"x",rate:42}],它将覆盖ratecode="x"

【讨论】:

  • 非常感谢。我将对其进行测试并检查您的答案。 :)
  • @SM 在您最近添加之后,您缓存的currency 查询是什么样的?由于它已经完成,您将无法将 Query 的 Query 转换为存储过程。您还需要原始查询的详细信息。
  • 添加了在 application.qry.currency 未定义时调用另一个函数 initCurrencyRecordset 的代码。 @肖恩
  • @SM 我不知道您的数据库是什么样的,但似乎缓存的查询除了过滤之外并没有真正对JOINed 表 (scs_fm.dbo.currency_code) 做任何事情从SCS_FM.dbo.currency 中删除没有相应行的任何记录。我回家后会再看一下这个,但是你能从你的数据库中提供任何样本数据吗?我认为您可以编写一个新的存储过程或查询,只需一次调用即可获得所需的内容。
  • 查看dbfiddle.uk/…,了解如何重构存储过程的查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多