如何获取关联数组符号来分配简单值

时间:2015-06-17 02:59:28

标签: coldfusion coldfusion-11

我使用Microsoft SQL Server Northwind演示数据库创建了示例代码。如果您无法访问此演示数据库,则可以使用一个简单的(MS-SQL)脚本来创建此问题的表和一行数据。

CREATE TABLE [dbo].[Products](
    [ProductID] [int] IDENTITY(1,1) NOT NULL,
    [ProductName] [nvarchar](40) NOT NULL,
    [SupplierID] [int] NULL,
    [CategoryID] [int] NULL,
    [QuantityPerUnit] [nvarchar](20) NULL,
    [UnitPrice] [money] NULL CONSTRAINT [DF_Products_UnitPrice]  DEFAULT (0),
    [UnitsInStock] [smallint] NULL CONSTRAINT [DF_Products_UnitsInStock]  DEFAULT (0),
    [UnitsOnOrder] [smallint] NULL CONSTRAINT [DF_Products_UnitsOnOrder]  DEFAULT (0),
    [ReorderLevel] [smallint] NULL CONSTRAINT [DF_Products_ReorderLevel]  DEFAULT (0),
    [Discontinued] [bit] NOT NULL CONSTRAINT [DF_Products_Discontinued]  DEFAULT (0),
 CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED 
(
    [ProductID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[Products] ON 
GO
INSERT [dbo].[Products] ([ProductID], [ProductName], [SupplierID], [CategoryID], [QuantityPerUnit], [UnitPrice], [UnitsInStock], [UnitsOnOrder], [ReorderLevel], [Discontinued]) VALUES (1, N'Chai', 1, 1, N'10 boxes x 20 bags', 18.0000, 39, 0, 10, 0)
GO
SET IDENTITY_INSERT [dbo].[Products] OFF
GO

这是ColdFusion代码:

<cfset variables.useTempVar = false>

<cfquery datasource="Northwind2014" name="qryNWProducts">
SELECT TOP 1 * from Products;
</cfquery>

<cfdump var="#qryNWProducts#" label="qryNWProducts">

<cfset variables['stProduct'] = {}>
<cfloop index="vcColName" list="#qryNWProducts.columnlist#">
    <cfif variables.useTempVar>
        <cfset variables['temp'] = qryNWProducts[vcColName]>
        <cfset variables['stProduct'][vcColName] = variables.temp>
    <cfelse>
        <cfset variables['stProduct'][vcColName] = qryNWProducts[vcColName]>
    </cfif>
</cfloop>

<cfdump var="#variables['stProduct']#" label="variables['stProduct']">

<cfloop collection="#variables['stProduct']#" item="key"><cfoutput>
    variables['stProduct']['#key#'] JVM datatype = #getMetadata(variables['stProduct'][key]).getName()#<br>
</cfoutput></cfloop>

<br>
This always works:<br>
<cfset variables['aPhrase'] = "I ordered " &  variables.stProduct.ProductName & " for " & DollarFormat(variables.stProduct.UnitPrice) & ".">
<cfoutput>#variables['aPhrase']#<br></cfoutput>

<br>
With &quot;variables.useTempVar = false&quot;, the next line will throw a &quot;Complex object types cannot be converted to simple values. &quot; error.<br>
<cfset variables['aPhrase'] = "I ordered " &  variables['stProduct']['ProductName'] & " for " & DollarFormat(variables['stProduct']['UnitPrice']) & ".">
<cfoutput>#variables['aPhrase']#<br></cfoutput>

上面的代码在顶部有一个名为“variables.useTempVar”的布尔变量,可以翻转以查看我得到的错误。

从查询到结构的直接赋值(当variables.useTempVar = false时)看起来导致结构值为JVM类型“coldfusion.sql.QueryColumn”。

另一个注意事项:如果这行代码:

<cfset variables['stProduct'][vcColName] = variables.temp>

更改为:

<cfset variables['stProduct'][vcColName] = variables['temp']>

JVM数据类型为“coldfusion.sql.QueryColumn”。

当点符号临时变量用于分配查询字段时(当variables.useTempVar = true时); JVM数据类型是与数据库列类型(java.lang.Integer,java.math.BigDecimal,java.lang.String等)非常匹配的简单类型。

我也经历了这样的陈述,并提供了一些奇怪的结果:

<cfset variables['stProduct'][vcColName] = qryNWProducts[vcColName].toString()>

这是问题所在。这是将简单值从查询转移到结构的最佳方法吗?强制使用临时变量和点符号来实现这一点似乎很奇怪。

评论:我一直认为点符号和关联数组符号是等价的。这个代码示例似乎与该意见相矛盾。

2 个答案:

答案 0 :(得分:3)

@Leigh是正确的,因为在对查询对象使用关联数组表示法时需要提供行号。因此,您可以引用第1行,如:qryNWProducts[vcColName][1]

关于你的问题

  

这是将简单值从查询转移到结构的最佳方法吗?

您确定需要结构吗?您的问题并没有真正指定用例,因此完全有可能最好按原样使用查询对象。

如果您确实需要它作为结构(并且因为您使用的是ColdFusion 11),我建议您查看serializeJSON/deSerializeJSON将其转换为结构。 serializeJSON有一个新属性,可以将查询对象正确地序列化为&#34; AJAX友好&#34; JSON结构数组。然后,您可以将JSON deSerialize为CF数组,如下所示:

NWProducts = deSerializeJSON( serializeJSON( qryNWProducts, 'struct' ) )[1]; 这将返回该查询对象中第一行的结构表示。

虽然从the Adobe docs for serializeJSON开始并不明显,但第二个参数可以是以下参数之一:true|false|struct|row|column这将改变格式化结果数据的方式。

此处使用上述技术runnable example展示了每个serializeQueryAs选项。

开始将这类代码移入cfscript也是一种更好的做法。 queryExecute非常易于使用,并且可以很容易地开发基于脚本的查询。有关如何开发基于脚本的查询的更多信息,请参阅trycf.com上的How To Create a Query in cfscript教程。

最后的注意事项,这有点偏离主题,但在命名变量时不使用Hungarian Notation是一种普遍接受的最佳做法。

答案 1 :(得分:2)

@ Abram覆盖了主管的答案,但只是拿起你提出的一个切线点。

点符号和关联数组符号 在CFML中通常是等价的。但是在查询的情况下,存在轻微的变化。点符号:query.columnName被视为query.columnName[currentRow]的简写(其中currentRow默认为1)。

带有查询的关联数组表示法没有这个“语法糖”,因此query["columnName"]指的是整个列,正如语法实际指示的那样。

在CFML中没有我知道的函数将查询列作为参数,但是如果在数组函数中使用它,CFML引擎会将列转换为数组。这有时非常方便。