MS Access Date() syntax in query to SQL Server - sql-server

I have found several posts on using the GETDATE() function for SQL Server linked table while in an Access front-end VBA procedure. Those posts are focused on the WHERE clause of the query, but I have been unable to find corresponding information on use of GETDATE() for column assignment.
For example, I understand that in the WHERE clause, I would use something like this:
WHERE MyDate = CAST(GETDATE() AS DATE)
However, I am getting syntax errors in VBA when I try to assign the current date to a column, like this:
INSERT INTO MyTable ( SomeValue, TheDate ) SELECT 'Widget' AS Expr1, CAST(GETDATE() AS DATE) AS Expr2;
In this example, TheDate is defined as DateTime in SQL Server. Written like this, VBA reports "Syntax error (missing operator) in query expression 'CAST(GETDATE() AS DATE)'. I tried to surround the expression with Access-friendly # date delimiters, but no luck there.
After spending about 30 minutes searching stackexchange.com various ways for MS Access Date() in SQL, I have been unable to find this. However it is so simple I am sure it was already answered somewhere.

In MS Access you likely (not 100% sure for linked SQL, you have to experiment) should use Now() and Date() functions. First one is equivalent to getdate() in SQL, the second one returns current date without time.

If you run this in Access on a linked table (not a PT query), it should read:
INSERT INTO MyTable ( SomeValue, TheDate )
VALUES ('Widget', Date());

There seems to be some confusing here. If you building a Access query, then ZERO ZERO of the SQL server date functions and syntax matter. Your SQL MUST continue to be written to Access standards unless you using a pass-though query.
However, I seen this 100x times here.
What is the data type on sql server side?
Is it datetime, or datetime2?
And double, triple, qudadropes, (and more) check the linked table in desing mode.
If you link to SQL server using the standard legacy "SQL Server" driver. The one that been shipped for 20 years since windows 98SE?
You MUST check if Access is seeing those columns as text, or as date columns (which in Access always allow a time part if you want).
Access code, queries, forms and EVERYTHING should require ZERO changes if you migrate that data from Access to SQL server and link the table. Again: ZERO ZERO changes.
However, if you used datetime2 on the SQL server side? Then you CAN NOT use the legacy "SQL server driver" when linking table. The reason is they don't support the newer datetime2 format. As a result, Access will actually see, use, and process that column as a text column. You REALLY, but REALLY do not want that to occur.
Why?
Becuase then you spend the next week asking questions on SO about how some date code or column or query does not work.
again:
ZERO ZERO changes are required in Access. If your dates are starting to break, then the issue is not date formats, but that column is now being seen by access as a TEXT data type.
Soltuion:
Either change the sql side datetime2 columns to datetime, and re-link.
or
re-link your tables using a newer native 11 (or later - up to 18 now). that way, access will see/use/process the datetime2 as a correct date format in Access.
So, before you do anything? Open one of the Access tables linked to SQL server in design mode. (ignore the read only prmompt). Now, look at the data type assigned to the date columns. If they are text, then you have a royal mess.
You need to re-link using the newer ODBC drivers.
Zero of your existing code, sql and quires should be touched or even changed if you using a linked table to sql server. But then again, if you linked using the wrong SQL ODBC driver, then Access cannot see nor process those datetime2 columns as date - it will be using text, and you beyond really don't want to allow that to occur.
In summary:
Any date code, SQL updates, sorting, query, VBA code, form code, reports should continue to work with ZERO changes. If you are making changes to dates after a migration, then you done this all wrong, and those date columns are not being seen by access as date columns.
Either get rid of all datetime2 columns and then re-link (change them server side to datetime). Or re-link the tables using a native 11 or later ODBC driver. Either of these choices will fix this issue.
This is a fix that requires ZERO code, and zero changes to Access dealing with dates.

Related

Date format changed on imported SQL Server DB

I have migrated a SQL Server database from one server to another. I did this via export to BAK and then Restore on the new machine.
Seems to be a different format somewhere, as a simple query that was working previously, is now throwing an error, but I cannot see what it might be (collation and 'containment' info seem the same).
The old SQL Server version: Microsoft SQL Server 2012 - 11.0.6598.0 Express Edition
The new SQL Server version: Microsoft SQL Server 2019 - 15.0.2080.9 Express Edition
The error, below, refers to a date format:
SELECT userID FROM tblLogin
WHERE CAST('30/09/2021 00:52:14' AS datetime) < DATEADD(n,600,accessDate)
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
(Column accessDate is of type datetime, null)
Always always ALWAYS use the ISO-8601 date formats for literals in Sql Server. For historical reasons, the preferred option for date-only values is different than date-time values, so you want either yyyy-MM-ddTHH:mm:ss for date and time or yyyyMMdd for date-only. But the really important thing is always go in order from most significant (year) to least significant (second).
Anything else isn't really a date literal at all: it's a string you must convert to a date.
If we follow this correct convention (because anything else really is incorrect), you get it down to this (which doesn't even need the CAST() anymore, because Sql Server can interpret it as datetime from the beginning):
SELECT userID
FROM tblLogin
WHERE accessDate > DATEADD(n, -600, '2021-09-30T00:52:14')
Also note I inverted the check, moving the DATEADD() function to act on the literal, instead of the column. This is always preferred, because it can work with any index you may have on the accessDate column. The original code would have rendered any such index worthless for this query.

Why am I seeing values of '2432-82-75 50:08:01' in Oracle DATE column?

As part of my job duties, I'm responsible for extracting data from our vendor's Oracle 11g database, and loading it into our SQL Server 2016 database. I've been doing this successfully with SSIS and the Attunity Oracle connectors.
Today I was informed that there was a new column added to the existing Invoices table on the Oracle side. There was already a DATE column called Order Date, which contains valid date values with zero'd times, like 2017-12-25 00:00:00.
The new column is called Order Date Time and is also a DATE column. When I opened up the SSIS package and pulled up the Oracle source in my DFT, I previewed the data and found the values in Order Date Time to be 2432-82-75 50:08:01. I tried converting the column with CAST and all the TO_* functions, but the conversions either failed outright, or returned a string of zeros.
TO_CHAR("Order Date Time", 'YYYYMMDDHH24MISS')
yields 00000000000000
After a bit of Googling for "Oracle date value invalid", I'm now thinking that these DATE values are actually corrupted. Am I missing anything here? Is there some sort of special Oracle-specific technique for storing time values in a DATE column that I may not be aware of?
(And yes, it does bother me quite a bit that our vendor added another DATE column instead of just using the time portion of the existing Order Date column.)
Unfortunately, Oracle database engine allows inserting invalid date values, which leads to many problems especially when importing data to others database engines such as SQL Server.
To handle this issue, you have to implement the logic that fits your needs, as example:
You can exclude these records from you queries by filtering on acceptable date ranges: (WHERE date between ...)
You can Update records with invalid values by replacing with NULL
You can use a CASE statement in your query to replace values with NULL
I faced this issue one time while importing data to SQL Server from an Oracle data source, there was unacceptable date values, i decided to update all records where date are invalid and replace with NULL values before starting the import process.
There are many links related to this issue:
Detecting invalid values in the DB
How to identify invalid (corrupted) values stored in Oracle DATE columns
Corrupt date fields causing query failure in Oracle
Invalid Date in DATE Column SQLPlus VS SQLDeveloper
Ask Tom - date validation in oracle
Dealing with invalid dates
Error: Invalid date format
DB Connect; Oracle DB date field data is corrupt

SQLBulkCopy and Dates (1/1/1753)

I've got an application which has been working fine for quite a while, but there is an annoying item that continues to get in the way on occasion.
Let's say that I use an object such as OracleDataReader or MySQLDataReader to pass the data to the sqlbulkcopy object for insert. Let's assume that all the columns maps just fine and for the most part, it all works well.
Granted, I don't have control over the source application or database (which is either MySQL or Oracle). So some goof goes into a different application and puts in a date on the invoice table of 5/31/0210. He really meant to put in 5/31/2010, but the application he's using is not validating the data very tightly and the Oracle database accepts it. For all intensive purposes, the data of 5/31/0210 is a valid date for the Oracle db. It might be stupid in terms of data entry, but it is what it is at this point.
Now our OracleDataReader comes along and is transferring this invoice table over to SQL Server via the SQLBulkCopy. It is passing the data to perfectly matched table with the right column names and data types. You can see what is going to happen. This date of 05/31/0210 from Oracle is not accepted by the SQL Server db engine, as the DATETIME field only allows dates from 1/1/1753 to 12/31/9999.
When it encounters this record, it simply fails and gives an overflow error. It doesn't skip the record, it kills the feed. So if it happens a thousand records in on a million record table, you don't get the remaining 999,000 records.
Is there anyway to get around this issue so that the feed will continue?
Ideally, I'd like to move the receiving SQL Server DB to 2008 and use DATETIME2, which would allow for these goofy dates, but unfortunately not all my clients are ready to move to this version yet, so I'm stuck with DATETIME in SQL 2000/2005/2008.
Any ideas on how to get around this without changing the SQL? Ideally, I wouldn't mind if it just skipped the record. I know that I could do this in the SQL for the datareder, but this would be extremely complicated when you have twenty date fields in a single query. It would be maintenance nightmare.
Any thoughts would be appreciated.
One option would be to change the datetime column type to varchar. Then add a derived column for converting the string to datetime. The trick would be to use a function in the derived column to validate the date and put an arbitrary datetime if the coversion will fail. If you do heavy date comparisons, persist the computed column and/or index it.
I say all of this under the impression that sqlbulkcopy is not able to do transforms. Maybe you can. Hopefully, someone will chime in with a way to.
SSIS would be great in this situation, as you could do the transform and also get the performance benefits of the bulk update lock.

CAST for Format() a DateTime to Date on both SQL Server and MS Access

I have an application that can use either SQL Server or MS Access as the data store.
In one table, I have a DATETIME column. I would like to retrieve the value as a DATE value (with the time part stripped off).
I can do that in SQLServer with CAST() and in MS Access with Format(). Ideally, I would like a single SQL query that could be applied against either database instead of sending a slightly different query to each database. Does anyone know a trick to do this?
Use DATEADD/DATEDIFF
Sql Server
SELECT DATEADD("d", DATEDIFF("d", 0, getdate()), 0) as someDateOnly
MS Access
SELECT DATEADD("d", DATEDIFF("d", 0, Now()),0) AS someDateOnly;
Just use a field name in place of GetDate() and Now()
E.g.
SELECT DATEADD("d", DATEDIFF("d", 0, [somefield]),0) AS someDateOnly;
as an aside DateAdd/DateDiff is the way you want to go if you want to strip the time in versions prior to 2008 anyway.
Sometimes you run access (e.g. in development) and sometimes a sql server and you want to make sure it works in both?
There are only two way I know (which don't pretend to be final :)).
create all selects as queries either in your sql or access database.
Then in your code you access the queries only
develop a database layer where you statements will be parsed and
handle each database.
Since the syntax is different there is no other way I know...

Linked Informix table in MS SQL Server ignoring criteria?

I’m having a problem with a linked Informix table in MS SQL Server 2008r2. When I query this table, it seems to ignore some of the criteria I’m passing to it but not others. For example if I put a condition on the rowdate field the remote query part of the execution plan does not show any WHERE clause but if I put criteria on another field such as ACD it does show.
It seems it does not pass any criteria on the rowdate field but does on all others.
I know the field is indexed on the Informix side. If it helps the table I’m linking is from Avaya CMS and it is linked via the OpenLink ODBC driver.
EDIT:
As far as I know it is Informix Dynamic Server 2000 and it is on Solaris. The column comes up as a DATE data type which is correct. I have tried passing the criteria as ‘2010-08-03 00:00:00’, ‘2010-08-03’, CONVERT(date,’2010-08-03’) and a few more variations. When the data is returned to SQL server it is in the format yyyy-mm-dd.
When I view the execution plan I can see the remote query with all the other criteria followed by a filter for only the rowdate field.
I know that rowdate is indexed and that the driver does normally communicate that information as we use it in other applications (Business objects and MS Access) and they don’t have a problem
I managed to figure it out but it is the strangest thing ever. I went down the route of passing the date in different formats. My default is to use the normal YYYY-MM-DD that of course did not work so I tried YYYY-MMM-DD, still nothing. After going through LOTS of combinations I found one that works Mmm-DD-YY and it has to be exactly that! SEP-21-2010 wont work but Sep-21-2010.
I wonder if this is just a strange hang up from Informix or something in the driver, anyway it works.
On a side note has anyone noticed how strange it is that people from the America write the date month, day year? Stop and think about it for a second, do you say the number 2410 as “Four hundred, ten, two thousand”? The best part about it is try asking yourself this, what day is American independence day? Most Americans say “That’s easy you limey person it is the 4th of July” hmmmm day month (year), the only date they say round the right way is the date they got their independence. I will leave it up to the SO community to see the irony in that
Example query below:
select *
from OPENQUERY (AVAYA, 'select row_date,starttime,intrvl,acd from root.hagent where
row_date = ''NOV-22-2012'' and acd = 1 and split = 1 and starttime = 1900')
By the way I managed to extract accurate data via both MMM-DD-YYYY and Mmm-DD-YYYY.

Resources