Using a datetime parameter with ADO (ODBC) loses time part

后端 未结 2 1855
余生分开走
余生分开走 2021-01-18 04:17

I stumbled onto this problem yesterday when I was busy writing some unit tests using SQLLite. My environment is Windows7/Delphi XE.

Using TADOQuery in conjunction wi

相关标签:
2条回答
  • 2021-01-18 04:35

    I have tested this a bit using SQL Server and have the exact same problem when I use MSDASQL.1 (ODBC). Your code works fine with SQLOLEDB.1 and SQLNCLI10.1.

    If you specify the parameter type to be ftString it will save with time using ODBC, (at least on SQL Server).

    Qry.Parameters.ParamByName('d').DataType := ftString;
    Qry.Parameters.ParamByName('d').Value := DateTimeToStr(DT);
    

    Note: Be careful of local settings when you use DateTimeToStr it might not produce what your db wants it to be. A safe bet would be to use yyyy-mm-dd hh:mm:ss[.fff].

    Update:

    You could also set the data type of the ado parameter to adDBTimeStamp yourself. ADODB sets it to adDate when you use ftDateTime.

    Qry.Parameters.ParamByName('d').ParameterObject.Type_ := adDBTimeStamp;
    Qry.Parameters.ParamByName('d').Value := DT;
    
    0 讨论(0)
  • 2021-01-18 04:54

    I had the same problem with VFPOLEDB (the Visual FoxPro driver) but the trick with adDBTimeStamp didn't work. FWIW, that's VFPOLEDB 9.0.0.5815 with Delphi 7 and also with RAD Studio 10 (Seattle).

    In the case of VFPOLEDB there is another possible workaround that is based on the fact that in Fox the underlying representation for date/time values (type 'T') is the same as that of the date values (type 'D') passed by OLEDB, i.e. a 64-bit double where the integer part represents days since January 1st in the year 0001 and the fractional part represents the time of day.

    If the table field has type 'T' and OLEDB passes a date then Fox coerces the value by doing nothing at all. So all that's needed here is adding back in the fractional part.

    Example, with start_time being a date/time field:

    cmd.CommandText := 'insert into foo (start_time) values (:start_time)';
    cmd.Parameters.ParamByName('start_time') := Now;
    cmd.Execute;
    

    This gives 2016-05-22 00:00:00 in the table.

    Now, add the fractional part like this:

    cmd.CommandText := 'insert into foo (start_time) values (:start_time + :fraction)';
    t := Now;
    cmd.Parameters.ParamByName('start_time') := t;
    cmd.Parameters.ParamByName('fraction') := Frac(t);
    cmd.Execute;
    

    This gives 2016-05-22 02:17:42. Even fractional seconds get preserved, although they do not get displayed.

    0 讨论(0)
提交回复
热议问题