SQL - Comparing between Dates in WHERE Statement not work correctly in Access DB - sql

I am trying to compare between two Dates in my SQL statement. The date format I use in my DataBase is DD/MM/YYYY.
When I write the following sql:
SELECT * FROM [MyTableName]
WHERE #03/10/2014# >= #02/11/2014#;
The result of the WHERE statement is True - (Not Good).
According to the format I wanted (DD/MM/YYYY) it should be False, But in the SQL Statement it appears in a MM/DD/YYYY format.
The same problem was appeared when I used the Now() Function:
WHERE NOW() >= #02/12/2014#;
(Today is the 03/11/2014)
It should be False because 11 < 12 but still the statement is True. (The SQL using the MM/DD/YYYY format).
So I Added a FORMAT function and now it looks like that:
WHERE FORMAT(#03/10/2014#, 'DD/MM/YYYY') >= FORMAT(#02/11/2014#, 'DD/MM/YYYY');
This time the result of the WHERE statement is Flase - (Good!).
So far the Format function looks like a good solution, BUT when trying to reformat the NOW() Date, the problem is appearing again:
This WHERE statement should be True
WHERE FORMAT(NOW(), 'DD/MM/YYYY') = FORMAT(#03/11/2014#, 'DD/MM/YYYY');
But it is False
While this WHERE statement should be False
WHERE FORMAT(NOW(), 'DD/MM/YYYY') = FORMAT(#11/03/2014#, 'DD/MM/YYYY');
And it is True
(Today is the 03/11/2014)
We can see that the Format function not working correctly on the NOW() Date.
Is someone have a solution for that?

Date literals, as delimited with # characters, will usually interpret values of the form NN/NN/NNNN in MM/DD/YYYY format - regardless of your culture settings.
In some cases, such as when the first set of digits is > 12, the environment may choose to interpret the value in DD/MM/YYYY order just to handle the input, but this is non-standard behavior that you should not rely upon.
Specifically, MSDN documentation for the VB Date Data Type says the following:
You must enclose a Date literal within number signs (# #). You must specify the date value in the format M/d/yyyy, for example #5/31/1993#. This requirement is independent of your locale and your computer's date and time format settings.
The reason for this restriction is that the meaning of your code should never change depending on the locale in which your application is running. Suppose you hard-code a Date literal of #3/4/1998# and intend it to mean March 4, 1998. In a locale that uses mm/dd/yyyy, 3/4/1998 compiles as you intend. But suppose you deploy your application in many countries. In a locale that uses dd/mm/yyyy, your hard-coded literal would compile to April 3, 1998. In a locale that uses yyyy/mm/dd, the literal would be invalid (April 1998, 0003) and cause a compiler error.
This is true for VB, as well as VBA and MS Access.
One way to work around this is to not use a date literal. Instead, consider using the DateValue function to parse the string to a date object before querying with it.

Related

SQL Server doesn't get date format dd-mm-yyyy

I'm trying to INSERT date variable into my SQL server.
The input format I'm trying to insert is: dd-mm-yyyy
And my SQL server column (which defined as type DATE) expect mm-dd-yyyy.
My PC date format is dd-mm-yyyy.
The error msg:
Conversion failed when converting date and/or time from character string.
Questions:
Why is the expected format mm-dd-yyyy and not dd-mm-yyyy?
How can I make the INSERT command work with this or another date format?
Thanks.
The format that your PC uses for dates doesn't matter when passing literal string for dates, the language setting for the LOGIN you are using to connect to SQL Server does. As the value is being interpreted as MM-dd-yyyy this very likely means that your language setting is (American) ENGLISH.
If, therefore, you are the only person that uses that LOGIN you may well want to change the language of your LOGIN to be appropriate for yourself. Most of the European languages, including BRITISH English (because the British don't speak English Microsoft? 😒) use the format dd-MM-yyyy.
Really, however, what you should be doing is using an unambiguous date format, of which there are only 2 in SQL Server, regardless of the language setting and data type. Those 2 formats are yyyyMMdd and yyyy-MM-ddThh:mm:ss.nnnnnnn. If you are always using the newer date and time data types (so not datetime or smalldatetime), then yyyy-MM-dd( hh:mm:ss.nnnnnnn) is also unambiguous, however, as it's language specific for the older data type then I don't normally recommend it's use.
Storage wise, date and time data types don't have a format, so your column isn't "expected" a value in the format MM-dd-yyyy, as it doesn't retain the "format data" that the value was passed in. Again, the only reason why a value like 13-12-2020 is working is because your language setting, which uses mdy for date interpretation.
Two things really,
Firstly, you can control the expected date format for each connection. Before issuing the insert statement, do set dateformat dmy; or set dateformat mdy; as appropriate.
Secondly, it's always advisable to work with dates in the ISO format of YYYYMMDD, so if you insert the data '20210314' it will always be treated correctly.

vba access Dlookup with dates in dd/mm/yyyy forma

I'm trying to get a value using a DlookUp, the problem is access formats my dd/mm/yyyy into mm/dd/yyyy despite using the Format function.
muestraAguasDatos = Nz(DLookup("[name]", "samples", "[location] = '" & location & "' AND ([name] LIKE
'*ACRT*' OR [nombre] LIKE '*CAWQ*') AND [sample_date] = #" & Format(sampleDate, "dd/mm/yyyy") & "#"))
This DLookup works when day value are > 12 but when it's lower and despite having the format it still format it to mm/dd/yyyy
Can you help me solving this issue please?
There are so many misunderstanding with MS Access date fields for non-US residents.
The basic rule is :
Whenever you specify a hardcoded date literal using #the date# notation, in
either :
an SQL query
a query filter criteria
in VBA
in a Dlookup() like you do
You should ALWAYS use the US date format : MM/DD/YYYY, or the ISO format YYYY/MM/DD
The confusion among Access beginners, comes from several things :
In the interfaces, by default, MS Access does an implicit conversion of the dates in the format that is defined on Windows Regional and Language Options setting of the computer. So non-US residents might have the impression that dates are always stored by default in the DD/MM/YYYY format, but that cake is a lie. Dates are stored as numbers, and it is just the display format that changes and is adapted following the computer settings.
In some cases, when you code date literals with #the date# in VBA or a Query, using DD/MM/YYYY format, it just works fine. The reason is date there's a check date algorithm in MS Office that validates a date and modify it to the right format in certain circumstances:
When your date begins by the year, MS Access is smart enough to detect it and it will then consider that your date is enterred in YYYY-MM-DD and do an implicit convertion to MM/DD/YYYY.
If the month part is higher than 12 and lower then 31, then MS Access will understand that this is in fact a DAY, and that you hardcoded the month at the other place. So for instance if you introduce 15th of September like this : #15/09/2019# it will implicitly be transformed in #09/15/2019#. However if you enters the 11th September like this #11/09/2019#, then Access will process it as 09th November !!!
Personal opinion, I have always found this last behavior plain stupid, because it may introduces a lot of troubles on applications of people not acquainted by that mechanism, and that tracking where the problems comes can be very tedious. It's sneaky, it should not be there. Much better to raise an error if the format is wrong.

TO_CHAR and TO_DATE use and the right context to use them

If I have a query like:
select *
from CAT_ACCT_AUDIT_TRAIL cataccount0_
where cataccount0_.CAAT_EXECUTED_DATE >=TO_DATE(’26-AUG-2016′, ‘DD-MM-YYYY’) AND
to_Date(TO_CHAR(cataccount0_.CAAT_EXECUTED_DATE , ‘dd -mon-yyyy’), ‘DD-MM-YYYY’)<=TO_DATE('31-AUG-2016', 'DD-MM-YYYY')
Here why do we require the to_char or to_date functions? What is the right context to use them?
If I do either of these:
select TO_DATE('26-AUG-2016', 'DD-MM-YYYY') from dual;
select TO_DATE('01-12-2016', 'DD-MM-YYYY') from dual;
I get the output in NLS variable format as I set in the session, irrespective of date input in format conversion; I get the same result for both. Wy is this so?
What is the correct way to solve this query? I mean when i need to fetch the values in date range.
You use to_date() to convert a string like '01-12-2016' to the date datatype. You use to_char() to convert a date to a string. In both cases you specify the format of the string - if you don't then your session NLS settings are used, which is not good practice for anything except ad hoc queries as someone else running your code later may get a different output or an error.
A general rule - which your code is following - is to compare data of one type with values/constants of the same type. As your column is a date, you're supplying the filter values as dates - by converting strings to the date datatype. If you didn't do that then implicit conversion would happen, but you should not rely on that either as it can also lead to NLS issues, and depending on the type it can prevent indexes being used. Read more about data conversion in the documentation.
Oracle tries to be flexible when interpreting the string when you do to_date(). When you do TO_DATE('26-AUG-2016', 'DD-MM-YYYY') you are supplying the month as a string (in a specific language, which is another topic), but telling the function to expect a number. Oracle 'helpfully' interprets that anyway, so it usually works. But whatever format you use for to_date(), you aren't specifying the display format, so your client is deciding how to display the converted date as a string for you - usually using your NLS settings, again.
Doing this:
to_Date(TO_CHAR(cataccount0_.CAAT_EXECUTED_DATE , ‘dd -mon-yyyy’), ‘DD-MM-YYYY’)
is usually pointless, but even so should be using consistent format models. One reason this is sometimes done is if the source date (caat_executed_date here) has its time set to something other than midnight, and you want to discard the time. But there are better ways to do that - specifically the trunc() function, which by default sets the time to midnight.
When you have constant values, like TO_DATE('31-AUG-2016', 'DD-MM-YYYY'), you can also use ANSI date literals, in the form of DATE '2016-08-31'.
It is unclear what you want to do, but you don't actually need those functions on constants. Just use the date keyword for date literals. For instance:
where cataccount0_.CAAT_EXECUTED_DATE >= date '2016-08-26'
If you want to remove the time component from a date, then use trunc():
where trunc(cataccount0_.CAAT_EXECUTED_DATE, 'dd') -- the `'dd'` is optional for this purpose
This can be used in any context where a date constant is accepted.

DATEDIFF working on yyyymmdd format SQL server

Why the DATEDIFF accepts yyyymmdd format ? Isnt it only for yyyy-mm-dd format ?
The function DATEDIFF(datepart, start_date, end_date) is working fine when the dates are in yyyymmdd format e.g.
DATEDIFF(DAY, 20161201, 20161231);
It gives answer 30
and if you do DATEDIFF(DAY, 20161201, 20161231) + 1 -- end date inclusive
It gives 31
Thanks,
Aiden
This can be a bit hard to tease out, but it is explained in the documentation, in the section "Supported String Literal Formats for date".
There are five sections on this (but the last two are API specific). The first section is affected by internationalization settings and has a bunch of different formats.
The second is the ISO 8601 format. I think the hyphenated format conflicts with the very last format in the first table ("yyyy dd mm" without the hyphens).
The final section has this informative line "A six- or eight-digit string is always interpreted as ymd". Hence, 'YYYYMMDD' is always interpreted correctly. Hence, this is the unambiguous format for date/time.
Note: Because the functions you are using expect dates, if the integer works, then it is converted to a date using its string representation. Normally, date constants should be in single quotes.
Actually its the sql server default format of dates but you can format your dates according to your requirements by following the link:
http://www.sql-server-helper.com/sql-server-2012/format-function-vs-convert-function.aspx

Oracle Implicit Conversion of String to date?

I work in T-SQL but have been given some Oracle PL-SQL for review on a Project.
Within the code there are Multiple WHERE clauses that do comparison of a Field of DataType = DATE against Strings which hold a "date".
ex:
WHERE to_date(mytable.mydatefield) > '23-OCT-2015'
OR
WHERE mytable.mydatefield > '23-OCT-2015'
Q1: Since "mydatefield" is already defined as a DATA type, isn't doing a "to_date" unnecessary?
Q2: Will Oracle do an implicit conversion on the '23-OCT-2015' and convert it to a date for comparison? I seem to remember encountering this before and comparing DATES to STRINGS caused issues?
Am I incorrect about that? If not can someone give me an example that I can use as evidence that it would not work?
A1: In general yes, but take the way Oracle handles implicit type conversions into account. The To_Date function around the mydatefield column expects a string input, so Oracle implicitly converts mydatefield to a string with a format matching the NLS_DATE_FORMAT session setting (which defaults to DD-MON-RR). Once converted to a string the To_Date function then converts it back to a date again using the current NLS_DATE_FORMAT setting. The newly reconstituted date is then compared to the string '23-OCT-2015', but since dates and strings aren't directly comparable the string value gets implicitly converted to a date using the current NLS_DATE_FORMAT setting. Depending on the value of the NLS_DATE_FORMAT setting, the first implicit conversion is likely to lose information specifically any time portion AND the original century, since the default NLS_DATE_FORMAT uses only a two digit year RR and no time component.
A2: Possibly, but it's best not to rely on it.
Both relations are poor programming for a couple of reasons. First they both are affected by implicit type conversions from dates to strings (or vice versa). Second they are both attempting to compare dates with strings in a non canonical form. As such 10-DEC-15 is less than 23-OCT-2015 because 1 is less than 2. Also note the difference in the number of digits representing the year since the default NLS_DATE_FORMAT uses a two digit year.
The correct method would be to compare the date column (possibly truncated) to a date string explicitly converted to a date
WHERE mytable.mydatefield > TO_DATE('23-OCT-2015', 'DD-MON-YYYY')
OR with truncation:
WHERE trunc(mytable.mydatefield) > TO_DATE('23-OCT-2015', 'DD-MON-YYYY')
which removes the time component of the date field.
Q1: According to Oracle, the first parameter of to_date() is a char value. Using it like to_date(date_value) you will force an implicit cast of date_value to char and then wrapping it again in a date value.
Q2: The server will do an implicit conversion from the string '23-OCT-2015' to a date value but based on database parameters which can differ from various servers(DEV vs PROD for example) so you should not rely on them. An example of correct usage would be WHERE mytable.mydatefield > to_date('23-OCT-2015','dd-MON-yyyy')
You should always use to_date/to_char to make sure you are using the correct format. Please see this answer for a more detailed explanation: Comparing Dates in Oracle SQL