我正在使用ColdFusion,并试图制作一个函数,使我能够获得特定帐户中特定列的值(每个帐户都是自己的记录/行)。
像这样的函数运行良好:
<cffunction name="getColumnValueFromAccount" access="public" returntype="string" >
<cfargument name="accountName" type="string" required="yes" />
<cfquery name="getColumn" datasource="mydatasource">
<!--- Note that the line below is 'hard-coded.' --->
SELECT role_ExampleSystem
FROM table_name
WHERE (accountName = <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="50" value='#accountName#'>)
</cfquery>
<!--- It's easy to return the column value when you know what its name was. --->
<cfreturn getColumn.role_ExampleSystem >
</cffunction>
但我真正想要的是一个函数,它允许我指定从哪个列名中读取,并消除了制作一组几乎相同的CF函数的需要,这些函数只有一个不同的硬编码SELECT参数。我想它应该是这样的,但我在实际读取我认为它应该返回的单个字符串时遇到了问题。
<cffunction name="getColumnValueFromAccount" access="public" returntype="string" >
<cfargument name="accountName" type="string" required="yes" />
<!--- Trying to accept a column name as an argument --->
<cfargument name="columnName" type="string" required="yes" />
<cfquery name="getColumn" datasource="mydatasource">
<!--- I'm trying to use cfqueryparam to add specify the column name to select. --->
SELECT <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="50" value='#columnName#'>
FROM table_name
WHERE (accountName = <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="50" value='#accountName#'>)
</cfquery>
<!--- This line doesn't work. --->
<cfreturn getColumn[#columnName#] >
</cffunction>
我认为您可以使用括号中的变量,如getColumn[#columnName#]
或getColumn[columnName]
,因为有人在评论中提到了它。但当我自己尝试使用变量时,它并没有像预期的那样起作用。我得到这个错误:
The value returned from the getColumnValueFromAccount function is not of type string. If the component name is specified as a return type, it is possible that either a definition file for the component cannot be found or is not accessible.
当我想获得cfquery的单个结果,但在查询的SELECT部分没有使用硬编码的列名时,你知道我应该采取什么路线吗?通常这个过程很简单,但当列名是一个变量时,情况似乎会有所不同。
查询是queryname[key][1]中的数组结构。
由于向后兼容性,它在第一个实例中起作用。从一开始,您可以执行queryname.columnname,CF将输出该列的查询的第一行。一旦切换到对象语法,它就不再以这种方式工作了。
在你的cfreturn中试试这个:
getColumn[columnName][1]
注意,在cfreturn示例中不需要英镑符号。
我的解决方案:
根据Leigh的建议,我不能以我尝试使用cfqueryparam
的方式使用它,以及Mark A Kruger的回答,我能够修改我的代码并使其工作。现在看起来是这样的:
<cffunction name="getColumnValueFromAccount" access="public" returntype="string" >
<cfargument name="accountName" type="string" required="yes" />
<cfargument name="columnName" type="string" required="yes" />
<cfquery name="getColumn" datasource="mydatasource">
SELECT #columnName#
FROM table_name
WHERE (accountName = <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="50" value='#accountName#'>)
</cfquery>
<cfreturn getColumn[columnName][1] >
</cffunction>
它现在正确地返回指定系统中帐户的角色,即,如果帐户accountName
是ExampleSystem
中的admin
,并且我在role_ExampleSystem
中作为ColumnName
传递给函数,则函数将按预期返回admin
。
警告:如果使用不当,我的解决方案可能存在SQL注入风险
在这样的SQL语句中使用ColdFusion变量不会提供任何SQL注入保护,因此允许用户在此处输入用于columnName
的数据是一个非常糟糕的想法。在我的情况下,这个函数只会被我编写的其他服务器端函数调用,并且用于columnName
的数据将在服务器端函数中进行硬编码。另一方面,accountName
是用户指定的,因此它在cfqueryparam
中是很重要的。
另一种更安全的解决方案:
Mark A Kruger提到,选择你可能需要的每一个专栏,然后读一读你真正感兴趣的专栏,这可能是一个更好的主意。这似乎是一个很好的主意。毕竟,获取一条记录的每一列(相关)不太可能是比我的单列示例大得多的数据库调用——除非你的数据库有大量列的巨大记录。你也可以这样做,作为一个副作用,你不需要担心SQL注入,在cfquery
中使用常规的冷融合#variable#
可能会让你打开。
阅读每个人的回答和评论都很有启发性。希望这个问题及其答案能帮助其他有兴趣在ColdFusion中做类似事情的人!