简体   繁体   中英

How to insert date from a coldfusion variable to a sql field?

Because of an unusual setup of code, instead of using cfquery with cfparam tags, I am instead building a sqlInsertCols list and a sqlInsertValues list and using those in an insert statement. Code something like this:

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

Firstly, are there any security issues with this, considering that both sql strings are populated within this code and not based on any user input?

And this has worked for several fields that I was inserting, but I just tried to add a date field and can't get the insert to work. The date is in the format "mm/dd/yyyy". Code to add date to sql lists:

sqlInsertCols = ListAppend(sqlInsertCols, "MyDateField");
sqlInsertValues = ListAppend(sqlInsertValues, myDateVar);

This runs with no errors but the value in the db is 1900-01-01 00:00:00.000 .

I've tried adding quotes around the date but can't seem to get it to insert properly. Is there any way to accomplish this?

SQL Sever uses single quotes around dates. Have you tried those?

First let me say that I simply don't like this approach. It appears that you are trying to use cfquery as a generic wrapper - a way to "plug in" lists of variables. That makes your queries obscured by other code. Seeing as how queries are the most vulnerable vector, not to mention usually containing user input, it makes everything harder to troubleshoot. Moreover, cfquery is a strength of the CF language - one of the few languages that you can cut and paste from a DB IDE and simple change the variable inputs (adding cfqueryparam of course).

Finally, your query NEEDS cfqueryparam to protect from SQLi - so in answer to the last part of your question - yes this code is vulnerable. There is rarely if ever a case for not using cfqueryparam.

So... here's a solution (which again, I don't like or recommend :) that you can use as a starting point:

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

This assumes that a field identified as a date is being inserted into a column in the DB of type "date". It also assumes that all the "other" non date fields are character fields. You might need to add checks for numbers or ints or whatever is in your data.

Additionally if you need to check the column name against the value you can use listgetat as follows:

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

Finally, for the completely not recommended quick and dirty solution you can try this:

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

This may work because of your RDBMS implicit conversion - which can convert down from character to date, int or numeric in many/most cases. of course you may just as easily get a syntax error.

One final note: the first and third samples above use some simple methods to insert commas in the list - comparing the value to the last value in the list and inserting if they don't match. So this assumes that any item coming not last in the list is not the same as the last item in the list. If that last item is duplicated elswhere in your query, then you will get a syntax error for a missing comma. Good luck!

ERRATA: FYI - on that last snippet - the single quotes OUTSIDE the variable are not escaped by CFQUERY .. so when you use '#varName#' - the single quotes are preserved, but when they are inside the variable they are escaped - because CF naturally assumes (and best practice dictates) that you are handling the contents to be inserted in variable form, and not query language itself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM