【问题标题】:Cf-script convert query result in structure with the unique key?Cf-script 将查询结果转换为具有唯一键的结构?
【发布时间】:2018-09-26 13:51:14
【问题描述】:

我的系统中有几个函数应该从 CFML 转换为 CFSCRIPT。在处理这个项目时,我遇到了这样的情况:我的结构输出的结果(很多空行)比它应该的多,甚至查询也只返回一行。这是我在 CFSCRIPT 中的代码示例:

cfstoredproc( procedure="GetZip", datasource=Application.dsnRead ) {
    cfprocparam( dbvarname="@Zip", value=trim(52401), cfsqltype="cf_sql_char", maxlength=5 );
    cfprocresult( name="ZipResult" );

}

local.strZip = {};
strZip[ZipResult.RecID] = {
    "City" : trim(ZipResult.City),
    "State" : trim(ZipResult.State)
};

writeDump(strZip);

这是我得到的输出:

array
1   [undefined array element]
2   [undefined array element]
3   [undefined array element]
4   [undefined array element]
5   [undefined array element]
6   [undefined array element]
7   [undefined array element]
8   [undefined array element]
9   [undefined array element]
10  [undefined array element]
11  [undefined array element]
12  [undefined array element]
13  [undefined array element]
14  [undefined array element] 
...

我想知道以结构输出查询结果并使用RecID 作为唯一键的最佳方式是什么?这个例子和上面的查询总是会同时返回 1 条记录,但我也想知道如果我需要用多条记录循环查询结果,这段代码将如何工作?

更新:我认为我找到了问题所在。 RecID 是我的数据库表中的自动增量 ID。例如,当我返回 RecID 时,该值可以是 56743。因此,如果我将 RecID 作为结构中的键传递,则会导致结构中出现如此多的行。我的问题是如何防止这种情况?有没有办法只设置密钥?

【问题讨论】:

  • 之所以发生是因为 CF 认为 strZip 是一个数组,而不是一个结构。我无法使用发布的 sn-p 复制它。能否请您发布完整的功能?还有,什么版本的CF?
  • @Ageax 我不确定如何在这里为 ColdFusion 创建有效的 sn-p。我使用 CF 2016。我不确定这是否只是因为我试图将结果转储到屏幕上...
  • @espresso_coffee 把整个函数贴在上面。您还可以使用手动查询创建 sn-ps,即。 QueryNew(),不过还是先看看函数
  • @espresso_coffee - 我们肯定需要查看完整的代码,因为到目前为止它还不能重现。建议在您的应用中有所不同。
  • 我真的不明白对一个有很多活动的问题的反对意见。但无论如何,我已经确认了这个问题以及我对范围界定问题的怀疑。 CFFiddle 显然配置了与您的服务器相同的范围搜索。我认为我比 TryCFs 更喜欢这个设置。无论如何:cffiddle.org/app/…

标签: struct coldfusion cfml cfquery cfloop


【解决方案1】:

我不确定您的 CF 为何将 strZip 转换为数组,但这就是您得到一堆空的原因。结构键可以是整数,但是当您告诉数组插入 x[42] 时,您的数组中将有 42 个元素。 local.strZip = {}; 非常明确地声明 strZip 是一个结构。但是,有时 CF 中的作用域会变得很奇怪。根据您使用它的方式,我认为当您执行strZip[ZipResult.RecID] 时,它可能会创建一个新的无作用域变量,它是一个数组。然后当你转储它时,你正在转储strZip 的数组版本。您可以尝试使用local.strZip[ZipResult.RecID],看看这是否会改变您的行为。或者尝试转储local.strZip 看看是否为空。

或者你可以这样做:

<cfscript>
    // Build a fake query object.
    ZipResult = queryNew(
        "RecID, City, State",
        "integer, varchar, varchar",
        [
              { RecID: 99, City: "Nashville", State: "TN" }
        ]
    );
    writeDump(ZipResult); // What's in our query?


local.strZip = {
    "#ZipResult.RecID#" : {
      City : trim(ZipResult.City) , 
      State : trim(ZipResult.State)
    }
};

writeDump(strZip);

</cfscript>

https://trycf.com/gist/28440630b0aa7ba1642e45bab3503652/acf2016?theme=monokai

注意:我无法在 TryCF 中复制您的行为,但我也不太可能在与您相同的范围内执行该代码。 确认:https://cffiddle.org/app/file?filepath=50f4e710-bd9b-40dd-a03a-15695bdd5a0d/c476f91b-6931-4295-be67-e4309aecfa0c/0492a7c6-029f-4227-941a-faee9da5a7cc.cfm

【讨论】:

  • 我不确定是什么导致了这个问题。只有我能做的就是使用structnew() 而不是= {}; 我不确定这是否会改变任何事情。
  • structNew()= {} 之间基本上没有区别。我的示例在结构中设置了一个结构,这似乎是您的初始代码所做的。
  • @espresso_coffee - 2 个不同的人无法使用发布的 OP 重现它这一事实强烈表明实际代码中的某些内容与您发布的 sn-p 不同。但如果没有实际的重现案例,我们都只是在猜测......请多花一点时间,并将实际重现问题的最少代码放在一起:-)
【解决方案2】:

你可以试试这个——

    var strZip = {};
    for ( i=1; i<=ZipResult.recordCount; i++)
    {
        strZip[ZipResult.RecID[i]] = {
             "City" : trim(ZipResult.City[i]),
             "State" : trim(ZipResult.State[i])
        };
    }

这样,我们将查询视为数组结构。

【讨论】:

    【解决方案3】:

    不,你是对的。因为它是一个整数,所以 ColdFusion 将数组填充到该整数的位置,因为你不能有一个包含一堆空值的数组;它们必须有一些价值,所以——正如你在这里看到的——它们是未定义的。 您不能将整数用作结构键。如果您在它的前面添加一个字母,然后在您引用它时将键砍掉该值,这将起作用。这很hacky,但这就是我通常为这类事情做的事情。 如果你想测试它,你可以使用 StructInsert() 而不是 []。

    【讨论】:

    • 是的,您可以使用整数作为结构键。但上下文很重要。 CF 需要了解它是一个结构。通常这种事情发生在变量类型不明确的情况下。 CF 不知道你想要哪个,所以它猜测。它看到一个整数并决定你想要一个数组。
    • 你是对的,我的评论具有误导性:如果你使用整数作为结构键,它不会引发错误,但这正是发生的情况:CF 将其转换为数组。我想另一种解决方法是设置 strZip.a = "" 或类似的,因此在开始添加数字键之前将其设置为结构,然后忽略该“a”键。我真的不知道哪个更不老套。
    • FWIW,您可以使用edit 更新答案。我怀疑原因是缺乏范围界定。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-21
    • 2012-08-16
    • 1970-01-01
    • 2019-06-01
    相关资源
    最近更新 更多