using Delphi 2010 (Firebird [testing], MS Sql Server, Oracle [production])
The following is my SQL
SELECT p.script_no, MIN(p.start_Time) as startTime, MAX(p.end_Time) as endTime,
SUM(p.duration) as TotalDuration
FROM phase_times p
WHERE (p.script_no=:scriptNo) AND (Trunc(p.start_time) >= :beginDateRange) AND (Trunc(p.start_time) <= :endDateRange)
GROUP BY p.script_no
ParamByName('beginDateRange').AsDate:= Date - 30;
ParamByName('endDateRange').AsDate:= Date;
I am getting a "conversion error from string - 10-25-2012" and i am not sure why, since my datetime fields are in the "10/25/2012 9:20:49 AM" format in the database.
If i change it to the following : ParamByName('beginDateRange').AsString := formatDateTime('mm/dd/yyyy',Date - 30).....i get the error "conversion error from string - 10/25/2012"
reserching this error has provided me no new avenues, do you have any ideas?
According to the Interbase 6.0 manual, Embedded SQL guide, chapter 7, Firebird supports conversion from YYYY-MM-DD and YYYY-MM-DD HH:MM:SS.qqq. I also believe it supports American style shorthand dates (eg 1-JAN-2012) for conversion.
It may be there are some locale dependent conversion supported, but in general: use an actual date/timestamp type instead of a string.
UPDATE
I initially did not spot the TRUNC in your query: it is the cause of the conversion error as this function only works on numbers, see the manual entry for TRUNC.
Given your comment (and the respons of ain) I assume you are only interested in the date part, and want to ignore the time. If so, rewrite your use of TRUNC to:
CAST(<your-timestamp-field> AS DATE)
And the condition (Trunc(p.start_time) >= :beginDateRange) AND (Trunc(p.start_time) <= :endDateRange) to:
CAST(p.start_time AS DATE) BETWEEN :beginDateRange AND :endDateRange
Firebird doesn't support conversion from string to date and time value if string is in 12 hour format. Use 'dd.mm.yyyy hh:mm:ss' or 'mm/dd/yyyy hh:mm:ss' formats.
String to date/time conversions usually use user's locale.
So if you feed a date/time conversion function with string that does not match your date part of the locale - you will get similar errors.
Also specifying date/time values like "10/25/2012" is Locale dependent. So if you execute your program on a computer with different than US Locale (like Mine) - it's likely to fail if using "10/25/2012".
To be Locale independent I suggest two options:
Use StrToDateTime, specifying TFormatSettings
Use ISO 8601 for specifying date/time strings (but I don't think Delphi supports that...)
BTW programs like MS Sql, Excel etc. accept dates in ISO 8601. But you have to check this for FB.
Regarding this:
...since my datetime fields are in the "10/25/2012 9:20:49 AM" format in the database...
The internal storage of date/time fields varies between different DB Engines. What you see in your DB Management Software ("10/25/2012 9:20:49 AM" in your case) is the string representation of the data field, usually formatted (again) according your user Locale
if you connected with DB from Firebird 1.0 under the server Firebird 2.1 (for example) you need todo backup and restore under Firebird 2.1
Related
I use an Oracle DB and access it using FireDAC.
I need to add to a select SQL request, two specific dates selected by the user. For that I am using two TDateTimePicker components.
I use DateTimeToStr() to convert the date from TDateTimePicker and build the SQL request like this:
FormRelatorio.FDQuery1.SQL.Add('and(PCPEDC.DTFAT) BETWEEN' +
''''+DatetoSTR(DateTimeInicial.Date)+'''' + 'and' +
''''+DatetoSTR(DateTimeFinal.Date)+'''');
Unfortunately, I get a syntax error from the DB because the DB does not accept nor auto adjust the system from month to numeral, accepting only their acronyms and in English (EX: JAN, FEB, MAR etc ...).
Is there any possibility of changing the result?
That is not a TDateTimePicker issue. It is an issue with how to pass a TDateTime (Delphi data type for date and time) to a SQL query. Currently you built a SQL string and so you must provide yourself the translation from date to string in the format accepted by the DB. This is possible but not the way to do it.
Instead, use a parametrized SQL query and FireDAC will do the work for you:
FormRelatorio.FDQuery1.SQL.Add('and (PCPEDC.DTFAT BETWEEN :InicialDate and :FinaleDate)');
FormRelatorio.FDQuery1.ParamByName('InicialDate ').AsDateTime := DateTimeInicial.Date;
FormRelatorio.FDQuery1.ParamByName('FinaleDate').AsDateTime := DateTimeFinal.Date;
This will correctly work if the columns in the database are correctly defined (You didn't showed the table structure).
If FireDAC doesn't do the correct job, you can use Oracle's TO_DATE function and Delphi FormatDateTime:
FormRelatorio.FDQuery1.SQL.Add('and (PCPEDC.DTFAT BETWEEN TO_DATE(''' + FormatDateTime('DD/MM/YYYY', DateTimeInicial.Date) + ''', 'DD/MM/YYYY') and
TO_DATE(''' + FormatDateTime('DD/MM/YYYY', DateTimeFinal.Date) + ''', 'DD/MM/YYYY'));
Oracle's TO_DATE accept a format DD/MM/YYYY and Delphi's FormatDateTime also. This avoid specifying month name.
Disclaimer: I have no Oracle DB available to check what I wrote. I did it from my head. You've got the idea...
I'm trying to resolve a bug in a archaic reporting tool that generates SQL dynamically and I'm running to a problem where I get a Data type mismatch error when the generated SQL queries a Date field from a Dbase table.
I've managed to replicate the same problem in a simple test app where the below query is loaded into a TADOQuery and activated.
SELECT *
FROM [QPERFSAL.DBF] QPERFSAL
WHERE ( QPERFSAL.PERFDATE = '21/01/2014' )
its obviously related to the date formatting but I've tried numerous formats but I still get the error
e.g. dd/mm/yyyy, mm/dd/yyyy, yyyy/mm/dd etc.
The obvious fix would be to used parameterised queries but as this is generated on the fly by a report tool, I can't use parameters :(
Is there something I'm missing or can I specify the date format at the ADO connection?
Thanks!
VFP OleDB Provider I believe also recognizes the DATE() function where you don't need to worry about yyyy-mm-dd or mm-dd-yyyy or dd-mm-yyyy formats. It will build into a proper date format column.
where QPERFSAL.PERFDATE = date( 2014, 1, 21 )
Now, if the "perfDate" column is that of a date/time, then you need to compare based on the date-only portion of the date/time field by using TTOD() (time-to-date function)
where TTOD( QPERFSAL.PERFDATE ) = date( 2014, 1, 21 )
Try to use as follows:
SELECT *
FROM [QPERFSAL.DBF] QPERFSAL
WHERE ( DTOC(QPERFSAL.PERFDATE) = '01/21/2014' )
Firstly, thanks to all that posted suggestions.
Alas, I tried them all but without success :(
thankfully, I found the solution while searching for something unrelated.
SELECT *
FROM [QPERFSAL.DBF] QPERFSAL
WHERE PERFDATE = Format('2014/12/06',"YYYY/MM/DD")
I'm not sure what effect this will have on localization but at least I can get the query to run now.
I am using Delphi 7, and Titan BTrieve to open a Pervasive Table.
It is a TtbTable component.
I am trying to apply the filter on a TimeStamp field with my code as follows:
Date:=InputDate;
DateString:=FormatDateTime('DD/MM/YYYY HH:NN:SS', InputDate);
Table1.Filter:='UPDATEDON > '+chr(39)+DAteString+chr(39);
Table1.Filtered:=True;
The problem is that the filter results are incorrect. It returns records that are before the do not match the filter criteria.
the Table1.Filter, filters the data in TDataSet not in btrieve/pervasive.
the problem is the date in string format... you must use the formar YYYY-MM-DD and not DD-MM-YYYY because the string compare.
in a string compare 17-06-2012 is grater than 16-07-2012, (17>16)
From the look of it, you are comparing strings, not dates.
What version of PSQL are you using? Is the UPDATEDON field defined as a Timestamp in the Btrieve database? If it's a timestamp, values are stored in 8-byte unsigned values representing septaseconds (10^-7 second) since January 1, 0001 in a Gregorian calendar, Coordinated Universal Time (UTC). It is not stored as a string.
Btrieve / PSQL stores dates in the 'YYYY-MM-DD' format.
WHat does a value from the UPDATEDON field look like? To use it as a filter, you need to make sure the filter value looks the same.
I hardcode a trial expiration date in my .net 2.5 app. how do I compare it with the user's system date such that the comparison is accurate regardless of the user's culture settings?
DateTime maxTrialDate = DateTime.Parse("11/17/2020", new System.Globalization.CultureInfo("en-US"));
DateTime curDate = DateTime.Parse(DateTime.Now.ToShortDateString(), new System.Globalization.CultureInfo("en-US"));
//the next line of code uses the DateDiff method to compare the two dates -dont recall its //exact syntax.
On my XP machine the above works if the control panel regional setting for datetime is en-US, but if I change it to en-AU, then the above code that sets curDate fires a FormatException "Date is not in a correct string format"
If you avoid using strings to represent the dates, you will not encounter this problem:
DateTime maxTrialDate = new DateTime(2020, 11, 17);
if (DateTime.Now.Date > maxTrialDate)
{
// expired
}
The DateTime is created by explicitly defining the day, month and year components, so the regional settings will not confuse matters.
What about just using CultureInfo.InvariantCulture all over the place?
You can use System.Globalization.CultureInfo.InvariantCulture
If I remember correctly, in most places outside the US, the standard date format is dd/mm/yyyy, rather than the US standard of mm/dd/yyyy. It might be that when trying to parse the date, it believes the 17 is the month, which is an invalid month, thus causing the error.
Why are you using the Parse method if you are hardcoding expiration date just compare it to
DateTime.now
The FormatException is expected since you explicitly ask the parser to use en-US.
Try calling the one-argument overload of DateTime.Parse(), or alternatively, if you really want to use the two-args overload (*cough*FxCop*cough*), something like:
using System.Globalization;
DateTime.Parse("11/17/2020", CultureInfo.CurrentCulture);
I'm trying to run the following db command against Informix:
delete from table1
where u_id in (select u_id
from table2
where c_id in (select c_id
from ptable
where name = 'Smith'
and dob = '29-08-1946'));
I pass this in as a string to the db.ExecuteNonQuery method in the MS Data Application block and I get the above error?
To get the date format '29-08-1946' to work, you need your DBDATE environment variable set to a value such as "DMY4-" (or "DMY4/"). These are standard variations for the UK (I used them for years; I now use "Y4MD-" exclusively, which matches both ISO 8601:2004 (Date formats) and ISO 9075 (SQL), except when debugging someone else's environment). There are other environment variables that can affect date formatting - quite a lot of them, in fact - but DBDATE takes priority over the others, so it is the big sledgehammer that fixes the problem.
One of the problems is that your notation using a plain string is not portable between US and UK (and ISO) settings of DBDATE. If you have a choice, the neutral constructor for dates is the MDY() function:
WHERE dob = MDY(8,29,1946)
This works regardless of the setting of DBDATE. You can probably use TO_DATE() too:
SELECT TO_DATE('29-08-1946', '%d-%m-%Y') FROM dual;
This generated '1946-08-29 00:00:00.00000' for me - the function generates a DATETIME YEAR TO FRACTION(5) value, but those convert reliably to DATE values in Informix.
You can also use the DATE() function or an explicit cast to DATE (either CAST('29-08-1946' AS DATE) or '29-08-1946'::DATE), but both of those are subject to the whims of the locale of the users.
Your date field is improperly formatted. Since there is no 29th month in the year 1946 that is what is causing the error.
I'd try just swapping the month and day. 08-29-1946.
The way the day and month parts of a date string are read in can depend on your computer's culture settings.
It is always safer to pass date strings to a database in the form 'dd-MMM-yyyy' (i.e. '29-aug-1946')
It's even safer to pass them as YYYY-MM-DD, the dd-MMM-yyyy in that example will fail on a server with a (for example) French locale.