Coldfusion更新查询在变量中使用语句时会引发错误

mpa*_*aul 3 sql-server coldfusion

尝试使用包含逗号分隔的列更新集的变量.该变量最终包含有效的SQL(或更准确地说是有效的Coldfusion语法),但查询引发错误:[Macromedia] [SQLServer JDBC Driver] [SQLServer]'<'附近的语法不正确.

我从一个初始列开始更新:

<cfset sqlString = myColumn & ' = <cfqueryparam value="#myValue#" cfsqltype="#myDataType#" null="#NOT len(trim(myValue))#">'>
Run Code Online (Sandbox Code Playgroud)

然后循环执行一些表单元素:

<cfset sqlString = sqlString & ', ' & myColumn & ' = <cfqueryparam value="#myValue#" cfsqltype="#myDataType#" null="#NOT len(trim(myValue))#">'>
Run Code Online (Sandbox Code Playgroud)

我当然最终在sqlString中使用了一个完整的字符串,但为了便于阅读,它包含这样的内容:

id = <cfqueryparam value="123" cfsqltype="cf_sql_integer">,
csp = <cfqueryparam value="5" cfsqltype="cf_sql_integer">,
Q185 = <cfqueryparam value="" cfsqltype="cf_sql_integer" null="YES">,
Q3 = <cfqueryparam value="" cfsqltype="cf_sql_integer" null="YES">,
Q177 = <cfqueryparam value="" cfsqltype="cf_sql_date" null="YES">
Run Code Online (Sandbox Code Playgroud)

所以我尝试在这样的更新查询中使用它:

<cfquery name="update_answers" datasource="#application.datasource#">
   UPDATE answers
   SET    #PreserveSingleQuotes(sqlString)#                                                     
   WHERE  rec_id = #id#
</cfquery>
Run Code Online (Sandbox Code Playgroud)

我在使用和不使用PreserveSingleQuotes功能的情况下尝试过此功能都无济于事.

如果我输出sqlString的内容并将其直接粘贴到查询中,它就可以正常工作:

<cfquery name="update_answers" datasource="#application.datasource#">
   UPDATE answers
          id = <cfqueryparam value="123" cfsqltype="cf_sql_integer">,
          csp = <cfqueryparam value="5" cfsqltype="cf_sql_integer">,
          Q185 = <cfqueryparam value="" cfsqltype="cf_sql_integer" null="YES">,
          Q3 = <cfqueryparam value="" cfsqltype="cf_sql_integer" null="YES">,
          Q177 = <cfqueryparam value="" cfsqltype="cf_sql_date" null="YES">                                                    
   WHERE  rec_id = #id#
</cfquery>
Run Code Online (Sandbox Code Playgroud)

同样,我在这里显示换行符以便于阅读,但是如果我将sqlString内容粘贴到带或不带换行符的查询中并不重要; 它会工作.

有任何想法吗?

Age*_*eax 5

tldr;

CFQueryparam不能嵌套在字符串中.它必须直接在<cfquery>标签中使用.要使用动态参数构建sql语句,请查看cfqueryparam的cfscript等效项.

安全问题

虽然你可能只是PreserveSingleQuotes()绝望地尝试,但是除非你理解这些影响,否则永远不要使用该函数,因为它基本上会在你的应用程序中创建一个很棒的大型SQL注入漏洞.

<cfset sqlString = sqlString & ', ' & myColumn

另外,要非常小心那种动态的sql语句.即使使用cfqueryparam 保护所有参数,查询仍然容易受到sql注入的影响,因为myColumn它是用户提供的值.不幸的是,cfqueryparam无法保护对象名称(表名,列名等),只能保护文字(字符串,日期等).因此,如果您绝对必须在原始sql中使用动态列名称,请确保针对白名单验证它们,并在检测到无效列时拒绝该请求.