【问题标题】:Looping over update query using script使用脚本循环更新查询
【发布时间】:2013-03-11 05:49:49
【问题描述】:

试图弄清楚如何使用脚本执行此循环。

<cfquery>
<cfloop from="1" to="#arrayLen(myData)#" index="i">
<!--- update query with different paramaters --->
</cfloop>
</cfquery>

我可以像这样在循环外进行,但速度很慢:

for(i=1; i LTE arrayLen(myData); i++)
{
    q = new Query();
    q.setSql(" UPDATE SQL HERE ");
    q.addParam(name="id", value=i);
    q.Execute().GetResult();
}

我想在 SQL 中做,而不是在它之外。

更新: 这是代码。我试图删除一些以使其更简单。

我有一个用户输入数据的表单,然后称为:

for(i=1; i LTE listlen(arguments.myStruct.myfield1); i++)   {           
    myfield1 = listgetAt(arguments.myStruct.myfield1,i);

    for(j=1; j LTE arguments.myStruct.count; j++) {
        maxvalue = form["max" & j];
        myType = form["myType" & j];
        id = myfield1;

        local.queryService = new Query();
        local.queryService.setSql
        ("          
            UPDATE  mytypes
            SET     maxvalue = :maxvalue,
                    myType = :myType
            WHERE   mytypeID = :id
        ");
        local.queryService.addParam(name="id", value=id);
        local.queryService.addParam(name="maxvalue", value=maxvalue, cfsqltype="cf_sql_integer");
        local.queryService.addParam(name="myType", value=myType, cfsqltype="cf_sql_integer");
        local.queryService.Execute().GetResult();
    }
}

【问题讨论】:

  • 你问的是cfscript中cfloop的语法吗? Using CFScript statements 不知道如何转化为 railo。
  • .. 或者您只是对基于标签的版本有问题?如果是这样,请发布您尝试过的sql 以及任何错误消息。另外,您的数据库类型是什么?您在谈论多少更新?
  • 我可以这样做:for(i=1; i LTE arrayLen(myData); i++) { q = new Query(); local.queryService.setSql("这里更新 SQL"); q.addParam(name="id", value=i); q.Execute().GetResult();但我想在 SQL 中做,而不是在它之外。
  • 其他问题呢:数据库类型和更新次数?
  • 对不起,我错过了。使用 MySQL 大约 100 个左右。

标签: coldfusion railo cfml


【解决方案1】:

重读Adam's response后,我同意我们需要查看原始更新查询。我不是 100% 确定你的目标是什么,但这是我的“猜测”。如果要更新多个不同值的记录,例如:

   UPDATE Table Col = 'xxx' WHERE ID = 1 ;
   UPDATE Table Col = 'yyy' WHERE ID = 2 ;
   ...

.. 您可以构建字符串并在循环中添加参数。请参阅下面对亚当示例的改编。请注意,您需要在数据源中启用“允许多个查询”设置才能使其正常工作。此外,请务必将 execute() 调用包装在事务中以保持数据完整性。

EDIT 根据您的更新修改了前面的示例:

<cfscript>
    // initialize these before any looping
    q = new Query();
    q.setDatasource("yourDSNHere");

    sqlArray = [];

    for(i=1; i LTE listlen(arguments.myStruct.myfield1); i++)   {           
        id = listgetAt(arguments.myStruct.myfield1,i);

        for(j=1; j LTE arguments.myStruct.count; j++) {
           // extract input values
           maxValue = form["max" & j];
           myType = form["myType" & j];

           // append a new statement
           arrayAppend(sqlArray, "UPDATE  mytypes 
                                  SET     maxvalue  = ?
                                        , myType = ? 
                                  WHERE myTypeID= ? "
                         );

           // add in the parameter values
           q.addParam(value="#maxValue#", cfSqlType="cf_sql_integer");
           q.addParam(value="#myType#", cfSqlType="cf_sql_integer");
           q.addParam(value="#id#", cfSqlType="cf_sql_integer");
    }

    // finally convert to single SQL string and run it
    q.setSQL( arrayToList(sqlArray, ";") );
    q.execute();
</cfscript>

【讨论】:

    【解决方案2】:

    我不太清楚您需要在循环中使用哪种信息,但一种方法是构建您的更新语句,然后将其输出到您的 cfquery 中。这是在 cfscript 中执行此操作的另一种方法:

    <cfscript>
    myData = ArrayNew(2);
    
    myData[1][1] = "test";
    
    myData[1][2] = "1";
    
    for (row = 1; row LTE ArrayLen(myData); row++) {
    
        queryService = new query(); 
    
        queryService.setSQL('UPDATE mytable SET myfield = "#myData[row][1]#" where table_id=#myData[row][2]#');
    
        result = queryService.execute();
    }
    </cfscript>
    

    【讨论】:

    • 警告,警告,sql注入危险 Will Robinson ;)
    【解决方案3】:

    很难说出你实际在问什么,但这可能就是答案?

    <cfscript>
    // dunno what your data is, but you need a col and a value so let's pretend you have those
    myData = [
        {col="col1", value="one"},
        {col="col2", value="two"},
        {col="col3", value="three"}
    ];      
    
    
    q = new Query(datasource="scratch_mysql");
    
    sql = "UPDATE tbl_test2 SET ";
    for (i=1; i <= arrayLen(myData); i++){
        q.addParam(value=myData[i].value);  // you might want a type here as well?
        sql &= " #myData[i].col# = ?";
        if (i < arrayLen(myData)){  
            sql &= ",";
        }
    }
    sql &= " WHERE id=1";
    
    q.setSql(sql);
    q.execute();
    </cfscript>
    

    在你把你的问题说得更清楚之前,我会投你的票。这是第一个需要澄清的&lt;cfquery&gt; 位:你现在在做什么。如果我们知道这一点,我们就会知道如何在脚本中告诉您如何操作。

    【讨论】:

    • 呵呵,从来不知道CF允许未命名的参数,即jdbc样式绑定?
    • 就在文档中:help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/…。它不是专注的,但它就在那里。这就是 CF 之前一直传递参数的方式。命名它们的能力是新的。查看参数化&lt;cfquery&gt; 的调试输出:占位符都是?
    • {smacks forehead} 好吧,我很尴尬地说我完全忘记了你可以从 cf9 开始使用 jdbc ? 语法 .. duh(也许在 Railo 的早期版本中)。最近有太多时间在旧版应用上工作。
    猜你喜欢
    • 2021-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-16
    相关资源
    最近更新 更多