Как перебрать хранимую процедуру в результате простуды - PullRequest
0 голосов
/ 25 октября 2018

Я хотел бы зациклить хранимую процедуру в 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>   

1 Ответ

0 голосов
/ 25 октября 2018

Основываясь на деталях, чтобы выполнить то, что вы просите .....

Я предполагаю, что ваша хранимая процедура выглядит примерно так:

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 scope, я предполагаю, что этот код находится внутри функции.Это позволит вам использовать ключевое слово var.

Обратите внимание, что dbvarname был проигнорирован после CFMX и восстановлен в обновлении 3. CF11. У CF11 был флаг JVM (-Dcoldfusion.ignoredbvarname), чтобы продолжать игнорировать dbvarname, но этот флаг игнорируется в CF2016 +.

Вы можете использовать простой цикл for для итерации по запросу, но, как я уже сказал выше, это может быть не тем, что вам действительно нужно.Если ваш запрос / sproc возвращает несколько результатов, он перезапишет origRate или toRate, если для них будет возвращено более одного значения.т.е. если ваш запрос имеет [{code:"x",rate:41},{code:"x",rate:42}], он будет перезаписан rate для code="x".

...