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



我正在使用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>

它现在正确地返回指定系统中帐户的角色,即,如果帐户accountNameExampleSystem中的admin,并且我在role_ExampleSystem中作为ColumnName传递给函数,则函数将按预期返回admin

警告:如果使用不当,我的解决方案可能存在SQL注入风险

在这样的SQL语句中使用ColdFusion变量不会提供任何SQL注入保护,因此允许用户在此处输入用于columnName的数据是一个非常糟糕的想法。在我的情况下,这个函数只会被我编写的其他服务器端函数调用,并且用于columnName的数据将在服务器端函数中进行硬编码。另一方面,accountName是用户指定的,因此它在cfqueryparam中是很重要的。

另一种更安全的解决方案:

Mark A Kruger提到,选择你可能需要的每一个专栏,然后读一读你真正感兴趣的专栏,这可能是一个更好的主意。这似乎是一个很好的主意。毕竟,获取一条记录的每一列(相关)不太可能是比我的单列示例大得多的数据库调用——除非你的数据库有大量列的巨大记录。你也可以这样做,作为一个副作用,你不需要担心SQL注入,在cfquery中使用常规的冷融合#variable#可能会让你打开。

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

相关内容

  • 没有找到相关文章

最新更新