如何将日期从coldfusion变量插入sql字段?
由于不寻常的代码设置,我不是使用带有cfparam标记的cfquery,而是构建一个sqlInsertCols列表和一个sqlInsertValues列表,并在insert语句中使用它们。代码如下:如何将日期从coldfusion变量插入sql字段?,sql,sql-server,datetime,coldfusion,Sql,Sql Server,Datetime,Coldfusion,由于不寻常的代码设置,我不是使用带有cfparam标记的cfquery,而是构建一个sqlInsertCols列表和一个sqlInsertValues列表,并在insert语句中使用它们。代码如下: <cfscript> var sqlInsertCols = ""; var sqlInsertValues = ""; // some looping and other processing here to fill the lists ... </cf
<cfscript>
var sqlInsertCols = "";
var sqlInsertValues = "";
// some looping and other processing here to fill the lists
...
</cfscript>
<cfquery datasource="..." name="insert">
INSERT INTO MyTable(#sqlInsertACols#)
VALUES (#sqlInsertVals#)
</cfquery>
运行时没有错误,但数据库中的值为1900-01-01 00:00:00.000
我尝试在日期前后添加引号,但似乎无法正确插入。有没有办法做到这一点?SQL Server在日期周围使用单引号。你试过那些吗 首先让我说,我就是不喜欢这种方法。看起来您正试图将cfquery用作通用包装器—一种“插入”变量列表的方法。这会使您的查询被其他代码掩盖。鉴于查询是最易受攻击的向量,更不用说通常包含用户输入,这使得所有问题都很难排除。此外,cfquery是CF语言的一个优势,是少数几个可以从DB IDE剪切和粘贴并简单更改变量输入的语言之一(当然可以添加cfqueryparam) 最后,您的查询需要cfqueryparam保护不受SQLi的影响-因此在回答问题的最后一部分时-是的,此代码易受攻击。很少有不使用cfqueryparam的情况 所以。。。这里有一个解决方案(我不喜欢也不推荐:)可以作为起点:
<cfscript>
var sqlInsertCols = "";
var sqlInsertValues = "";
// some looping and other processing here to fill the lists
...
</cfscript>
<cfquery datasource="..." name="insert">
INSERT INTO MyTable(#sqlInsertACols#)
VALUES (
<cfloop list="#sqlinsertValues#" index="colVal">
<cfif isDate(colVal)>
<Cfqueryparam cfsqltype="CF_SQL_DATE" value="#colval#"/>
<cfelse>
<cfqueryparam cfsqltype="CF_SQL_CHAR" value="#colval#"/>
</cfif>
<cfif colVal IS NOT listlast(sqlInsertValues)>
,
</cfif>
</cfloop>
)
</cfquery>
var sqlInsertCols=“”;
var sqlInsertValues=“”;
//这里有一些循环和其他处理来填充列表
...
插入到MyTable(#sqlInsertACols#)
价值观(
,
)
这假设将一个标识为日期的字段插入到DB中类型为“date”的列中。它还假设所有“其他”非日期字段都是字符字段。您可能需要为数据中的数字、整数或其他内容添加检查
此外,如果需要对照值检查列名,可以使用listgetat,如下所示:
<cfscript>
var sqlInsertCols = "";
var sqlInsertValues = "";
// some looping and other processing here to fill the lists
...
</cfscript>
<cfquery datasource="..." name="insert">
INSERT INTO MyTable(#sqlInsertACols#)
VALUES (
<cfloop from="1" to="#listlen(sqlinsertValues)#" index="x">
<cfif listgetat(sqlInsertCols,x) IS 'dateadded'>
<Cfqueryparam cfsqltype="CF_SQL_DATE" value="#listgetat(sqlInsertValues,x)#"/>
<cfelseif listgetat(sqlInsertCols,x) IS 'userid'>>
<cfqueryparam cfsqltype="CF_SQL_INTEGER" value="#listgetat(sqlInsertValues,x)#"/>
</cfif>
<cfif x IS NOT listlen(sqlInsertValues)>
,
</cfif>
</cfloop>
)
</cfquery>
var sqlInsertCols=“”;
var sqlInsertValues=“”;
//这里有一些循环和其他处理来填充列表
...
插入到MyTable(#sqlInsertACols#)
价值观(
>
,
)
最后,对于完全不推荐的快速肮脏解决方案,您可以尝试以下方法:
<cfscript>
var sqlInsertCols = "";
var sqlInsertValues = "";
// some looping and other processing here to fill the lists
...
</cfscript>
<cfquery datasource="..." name="insert">
INSERT INTO MyTable(#sqlInsertACols#)
VALUES (
<cfloop list="#sqlinsertValues#" index="colVal">
'#colval#'
<cfif colVal IS NOT listlast(sqlInsertValues)>
,
</cfif>
</cfloop>
)
</cfquery>
var sqlInsertCols=“”;
var sqlInsertValues=“”;
//这里有一些循环和其他处理来填充列表
...
插入到MyTable(#sqlInsertACols#)
价值观(
“科尔瓦尔”
,
)
这可能是因为您的RDBMS隐式转换——在许多/大多数情况下,它可以从字符向下转换为日期、整数或数字。当然,您也可能很容易出现语法错误
最后一点注意:上面的第一个和第三个示例使用一些简单的方法在列表中插入逗号-将值与列表中的最后一个值进行比较,如果不匹配则插入。因此,这假设列表中不是最后一项的任何项都与列表中的最后一项不同。如果最后一项与查询中的其他位置重复,则会出现缺少逗号的语法错误。祝你好运
勘误表:
仅供参考-在最后一个代码段中-CFQUERY不会转义变量外的单引号。。因此,当您使用“#varName#”时,单引号将被保留,但当它们位于变量内部时,它们将被转义,因为CF自然地假设(最佳实践要求)您正在处理以变量形式插入的内容,而不是查询语言本身。Try
sqlInsertValues=ListAppend(sqlInsertValues,CreateODBCDateTime(myDateVar))
@xpa1492-成功了!谢谢!如果你把它作为一个答案发布,我会接受它,它比@xpa1492的建议是首先创建日期变量,而不是字符串变量,然后再转换。不基于任何用户输入,确切的来源是什么?如果这些数据来自数据库中的另一个表,为什么不只是使用INSERT INTO/SELECT?否则,代码可能仍然存在sql注入的风险。另外,为什么不使用cfquery的cfscript版本?然后您可以使用cfqueryparam并获得绑定变量的性能优势。@DanBracuk-我们将日期作为字符串获取。它是从网页中刮取的。我已经尝试过了,但CF似乎将其转换为doubinsert语句中的le引号会导致错误。@froadie:您需要使用preserveSingleQuotes()
function.SQL服务器在日期周围不完全使用单引号。在字符串文本周围需要引号。在本例中是日期字符串。根据目标列,该字符串可能会隐式转换为date/time
,但它仍然是一个字符串。@froadie-引号加倍的原因是CF.querys的一个安全功能在不使用cfqueryparam时,sql注入存在风险,因此CF会自动将引号加倍,以防止出现这种情况。PreserveSingSingleQuotes
逆转了这种行为,但这样做会使您的db暴露在CF试图阻止的事情面前。因此请谨慎使用。加上1可以让Eric的声誉提高到足以发表评论的程度。感谢t他给出了详细的答案。其中一些是非常有用的。我将以某种方式重新构造它(我将为列名提供一种“查找”结构,这样我可以基于html提取它,但它仍然是受控的)。我可能会在循环中使用cfqueryparams。
<cfscript>
var sqlInsertCols = "";
var sqlInsertValues = "";
// some looping and other processing here to fill the lists
...
</cfscript>
<cfquery datasource="..." name="insert">
INSERT INTO MyTable(#sqlInsertACols#)
VALUES (
<cfloop list="#sqlinsertValues#" index="colVal">
'#colval#'
<cfif colVal IS NOT listlast(sqlInsertValues)>
,
</cfif>
</cfloop>
)
</cfquery>