当查询列为cfqueryparam变量时,从cfquery获取单个输出

时间:2016-04-07 19:06:14

标签: sql coldfusion cfquery cfqueryparam

我正在使用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]等括号表示法中的变量,因为有人在comment中提到了变量。但是当我试图自己使用变量时,它没有按预期工作。我收到这个错误:

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部分​​使用硬编码列名?通常这个过程非常简单,但似乎当你的列名是变量时,事情会变得有点不同。

2 个答案:

答案 0 :(得分:3)

查询是queryname [key] [1]中的数组结构。

由于向后兼容性,它在第一个实例中起作用。从头开始,您可以执行queryname.columnname,CF将输出该列的查询的第一行。一旦你切换到对象语法,它就不再那样了。

在你的cfreturn中试试这个:

getColumn[columnName][1]

注意 - 您的cfreturn示例中不需要井号。

答案 1 :(得分:1)

我的解决方案:

根据Leigh的建议,我不能以我尝试使用它的方式使用cfqueryparam,而Mark A Kruger的answer我能够修改我的代码并使其正常工作。它现在看起来像这样:

<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>

现在它正确地在指定系统中返回帐户的角色,即如果帐户accountNameadmin中是ExampleSystem,我将role_ExampleSystem传递给函数ColumnName 1}}该函数将按预期返回admin

警告:如果使用不当,我的解决方案可能会出现SQL注入风险!

在像这样的SQL语句中使用ColdFusion变量不提供任何SQL注入保护,因此允许用户输入 非常糟糕的主意 这里用于columnName的数据。在我的情况下,此函数将仅由我编写的其他服务器端函数调用,并且用于columnName的数据将在服务器端函数中进行硬编码。另一方面,accountName是用户指定的,因此它必须位于cfqueryparam

替代,更安全的解决方案:

Mark A Kruger mentioned,选择您可能需要的每一列并阅读您真正感兴趣的列可能是一个更好的主意。这似乎是个不错的主意。毕竟,获取记录的每个(相关)列不太可能是比我的单列示例大得多的数据库调用 - 除非您的数据库具有包含大量列的大量记录。您可以这样做,并且作为附带好处,您不必担心在#variable#中使用常规coldfusion cfquery的SQL注入可能会打开您。< / p>

阅读每个人的答案和评论非常有启发性。希望这个问题及其答案有助于其他有兴趣在ColdFusion中做类似事情的人!