Datatype mismatch when querying DBase Date field via a Delphi ADO Query - delphi

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.

Related

How can I filter my data down to a given Year or Month in a PSQL v13 Database

I get a syntax error in PSQL Control Center on an Actian 13 database when using Date_Part and I'm out of ideas on how to proceed.
There are two fields in the table I am querying 'Date' and 'CreateDate'. I get the same error when I involve either field. I have tried both 'month' and 'year' and have confirmed the field in the database is a Date field.
I have tried the following with no luck.
select date_part('month',CreateDate) from gl_trx3 where CreateDate = '2021-10-13'
I am using this specific date for example because there are records with that date saved.
The error message I get is below.
[LNA][PSQL][SQL Engine]Error in expression: date_part('month',CreateDate)
Anyone know what I am missing?
In the list of Time and Date Functions for Pervasive SQL13 the function date_part does not exist.
Using MONTH(dateexp) returns the month as an integer in the range of 1 to 12.

How to convert TDateTime to be used in a Oracle SQL request?

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

Need to change date formate to date (YYYYMMDD) format

Here the requirement is to convert sysdate to in to YYYYMMDD in date format. Here issue it converts this in string but I need this to convert in date format in YYYYMMDD form.
select to_char(trunc(sysdate-1),'YYYYMMDD') cdr_date from dual;
Would be easier to help if you mentioned what database you were using in your post or at least your tags. However based on the to_char function you are using I am assuming oracle. If that is right then the below code should help you out. I found this by simply googling oracle date format and going to the first link which is:
https://www.techonthenet.com/oracle/functions/to_date.php
Select to_date(trunc(sysdate-1),'YYYYMMDD') cdr_Date from dual;

conversion error from string, when using params in SQL

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

I'm getting "Invalid month in date" trying to run this?

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.

Resources