I'm looping through LDAP data placing some data from that into an MS SQL database. Out of the 7k+ LDAP records, a few have been causing an issue when trying to place the lastlogin into the database that has a DateTime format.
The problem is the date it has, 12/31/1600 7:00:00 PM, is not correct and causes an error of
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
The statement has been terminated.
I've been checking the date format before it inserts it into the database.
If Not IsDate(empInfo.lastLogon) Then
empInfo.lastLogon = Format(Now.AddYears(-1), "MM/dd/yyyy HH:MM:ss")
End If
But doesn't seem to catch the year of 1600 which seems to be causing that error above.
Is there any code I can use to detect those weird years and replace it with a random, legit date so it will place it into the database?
I think your problem is caused because what is a valid date in the code is not a valid date in the database, probably because the database can store an earliest date of 1753 something, whereas the code allows much earlier dates (such as the 1600 you cited).
Try adding a test for the year to your IF statement:
If Not IsDate(empInfo.lastLogon) OrElse empInfo.lastLogon.year < 2000 Then
empInfo.lastLogon = Format(Now.AddYears(-1), "MM/dd/yyyy HH:MM:ss")
End If
Instead of using a default of 1 year ago, you might want to use a marker value like 01/01/2000 00:00:00. This will let you easily identify ones which didn't have a "real" value. But I don't know your business rules, so YMMV.
For months use MM, but for minutes use mm.
I.e.; you should use MM/dd/yyyy HH:mm:ss instead of MM/dd/yyyy HH:MM:ss.
I hope it helps you.
I think you want something like this:
If Not IsDate(empInfo.lastLogon) OrElse DateTime.Parse(empInfo.lastLogon).Year < 2000 Then
empInfo.lastLogon = Format(Now.AddYears(-1), "MM/dd/yyyy HH:mm:ss")
End If
Related
I have a query that was working fine before a server migration and now is not working. I'm trying to convert all dates to a specific month and year, but I keep getting this error:
Conversion failed when converting date and/or time from character string.
Looking into the data, there are no null values in InputDate, which is a date data type column. When I run the Concat() function everything is formatted as 'YYYYMMdd', yet both CAST and CONVERT fail with the same error.
Is there an issue with my query that I'm not seeing?
SELECT RandoSTUFF,
DATEADD(day,2,CAST(CONCAT('2023','02',FORMAT(InputDate,'dd')) AS date)) AS MovedDate
FROM a_table_
I expect the issue is you have date values near the end of their months, and you're trying to compose the equivalent values for February, which is shorter.
So if you have an InputDate value of, say, 2022-12-31 and run the code in the question, it will extract the 31 and concat it with the other values, and you'll end up trying to do this:
CAST('20230231' as Date)
Of course, there is no such date.
As it is, it's not clear whether you want such an input to map to February 28 or March 3. To fix this, you'll need to rethink the problem so you only try to map to valid dates, and ensure the final result is more clearly defined. This is one of the many reasons it's almost always better to use Date/time functions instead of composing dates from strings.
I am using Business Objects, which runs on top of an Oracle SQL database. I do not have access to PL or any kind of SQL command line, and I do not have write access to the database. I can only run queries as single commands, requiring a defined set of columns to be output.
I am able to take data from user prompts, which appear in the SQL as:
#variable('Prompt1')
For example I can say:
SELECT
A.SomeDate
FROM
A
WHERE
A.SomeDate BETWEEN #variable('Start') AND #variable('End Date')
This is easy enough. It runs; requests the user to input some dates; and then returns all matches which are between them (inclusive).
The problem is, however, the users will be using Business Objects' "Infoview" system to run the queries, and the prompt system presents a date picker - which by default includes the time portion of the date ("01/01/2016 12:00:00 AM").
If the user does not delete the time portion, it can cause records to be missed, if the SomeDate value falls outside the selected time. For example, if I want to take all records of TODAY, then I technically want everything between 00:00:00 (midnight) and 23:59:59.
What I would really like to be able to do is use TRUNC around the query variable, as follows:
WHERE
A.SomeDate BETWEEN TRUNC(#variable('Start')) AND TRUNC(#variable('End Date'))
... however this causes a compilation error: "inconsistent datatypes: expected DATE got NUMBER". I don't know why Oracle would treat a prompt as a number datatype before it has compiled.
Does anyone know how I can take the #variable value and convert it into something that I will be able to truncate to a date value?
I'm therefore trying to figure out a way round this. One thing I had in mind was if I could possibly take the prompt variable and convert it explicitly into a date, using TO_DATE
Edit: it has been pointed out to me that TRUNC will have no effect, as the "12:00:00 AM" is already midnight. Therefore I think I have misunderstood TRUNC. It appears that it truncates it to midnight: whereas I thought it simply removed the time portion of the date altogether, meaning that matches would be returned at any time between 00:00:00 and 23:59:59.
What I really want is: if SomeDate has a time portion of, for example, 11:03 then how do I ensure that this will be included when an End Date prompt only specifies the day?
If you want to match SomeDate values between 00:00:00 on Start and 23:59:59 on End you can either adjust the end date to have that time instead of the default midnight, or use a range instead of between:
WHERE
A.SomeDate >= #variable('Start')
AND
A.SomeDate < #variable('End Date') + 1
The + 1 uses Oracle date arithmetic to give you the day after the variable value, so if the user picked "01/01/2016 12:00:00 AM" for both the start and end dates they would evaluate as 2016-01-01 00:00:00 and 2016-01-02 00:00:00 respectively. You can use the interval syntax if you prefer.
By using less-than for the upper limit you get all records where SomeDate is greater than or equal to the start date 2016-01-01 00:00:00 and less than the adjusted end date 2016-01-02 00:00:00 - which is the same as saying up to 2016-01-01 23:59:59. (Or if you has a timestamp column which has sub-second precision, up to 23:59:59.999...).
If the parser assumes the variable will be a string but it is actually a date - causing an 'inconsistent datatypes' error - then you could cast it to a date to satisfy the parser:
WHERE
A.SomeDate >= CAST(#variable('Start') AS DATE)
AND
A.SomeDate < CAST(#variable('End Date') AS DATE) + 1
or if it is actually passed as a string in the format you showed you can explicitly convert it:
WHERE
A.SomeDate >= TO_DATE(#variable('Start'), 'DD/MM/YYYY HH:MI:SS AM')
AND
A.SomeDate < TO_DATE(#variable('End Date'), 'DD/MM/YYYY HH:MI:SS AM') + 1
... making sure you have the correct format; from your example it could be DD/MM/YYYY or MM/DD/YYYY.
Try using TO_CHAR() and TO_DATE() together :
WHERE
A.SomeDate > TO_DATE(TO_CHAR(#variable('Prompt1'),'ddmmyyyy'),'ddmmyyyy')
First off, your problem is not coming from a time value in the prompt value, but rather the time value in SomeDate. Getting rid of that (making the date equal to midnight) will resolve the issue.
Your best bet, if you have the option of modifying the universe, is to create another object. I'm assuming you have an object named SomeDate whose SQL is a.somedate. Create another object, let's call it SomeDateOnly with a definition of trunc(a.somedate)* **.
Since SomeDateOnly will always be a midnight value, you can use Equal To with your prompts, which will produce SQL like:
trunc(a.somedate) = #variable('Prompt1')
which, when rendered by WebI, will produce:
trunc(a.somedate) = '16-08-2016 00:00:00'
This will return all records with a.somedate between 8/16/2016 at 00:00:00 and 8/16/2016 23:59:59.
Of course, you can use BETWEEN to select a range of dates:
trunc(a.somedate) between #variable('Start Date') and #variable('End Date')
Even if you don't have access to the universe, you can still use the above syntax by modifying WebI's generated SQL. (I'm assuming that's what you've been doing, anyway).
If the above works for you, then the following is irrelevant, but I wanted to address it anyway:
The reason for the "invalid number" error you were receiving is because of the way WebI formats dates for SQL. If you have this string in your query:
A.SomeDate = TRUNC(#variable('Prompt1'))
then WebI will replace the #variable(...) with a date string, and render it as the following before sending it to Oracle:
A.SomeDate = TRUNC('16-08-2016 00:00:00')
This, of course, makes no sense to the TRUNC() function as there's nothing to tell it that it's actually a date value.
You could to_date the prompt first, but you have to use the correct date format. WebI sets the nls_date_format for each session to a non-default format, so you would have to use:
A.SomeDate = TRUNC(to_date(#variable('Prompt1')),'dd-mm-yyyy hh24:mi:ss')
But again, this is irrelevant since you need to trunc somedate, not the prompt response values.
*Better still, rename SomeDate to SomeDateTime, and name the new object SomeDate
**This is pretty common - having multiple objects for the same source field. Sometimes you want the date/time value (for listing specific transactions), but sometimes you just need the date (for counting transactions by date). So having both available is very useful.
I am writing a SQL query for MS Access.
The two fields are DateTime. The start/end time are 22:30/6:30
When I run the following query
SELECT cDate(Format(table1.BeginTime,"hh:mm")),
I get 10:30 PM instead of 22:30. I do not want to convert to 12hrs format. How do I keep the Miliary time format?
So I tried a few things in Access 2013 and it seems that #Bjones has a point.
In SQL Server Format is a clr .net function and format(date, 'hh:mm') will be 12 hour and Format(date, 'HH:mm') will be 24 hour.
But as #Bjones pointed out there may be some question of how your original column is held as text or date or time..... And what I have concluded after trying is that your order of functions is wrong.
cDate(Format(table1.BeginTime,"HH:mm"))
cDate transforms the content to a date but it doesn't format it.
So
FORMAT(cDate(table1.BeginTime), "hh:mm")
or
FORMAT(cDate(table1.BeginTime), "HH:mm")
or
FORMAT(cDate(table1.BeginTime), "Short Time")
should give you what you want if the time is stored as text. If stored as date time you can just drop the cDate all together and stay with
FORMAT(table1.BeginTime, "Short Time")
as #Bjones answered.
You don't tell what the result of the query is intended for.
If you need the date value and to view this in 24 hour format, use:
Select table1.BeginTime
and apply a Format property for the column of h:nn or hh:nn
If you need the date formatted as a string in 24 hour format, use:
Select Format(table1.BeginTime, "hh:nn")
and no Format is needed.
In any case, even though the format string h:mm will work, do use h:nn or hh:nn, as m is for the month.
I think what you need to get rid of is the cDate function as your fields are already in DateTime format.
SELECT Format(table1.BeginTime,"hh:nn")
I'm new to MS Access and having trouble with using the BETWEEN AND function when applying to dates.
SELECT EmployeeID, FirstName, LastName, StartDate
FROM Chefs
WHERE StartDate BETWEEN #01/12/2015# AND #31/12/2015#;
The above gives me entries with the correct dates as well as entries with dates before the range, but not after.
Changing to
WHERE StartDate BETWEEN #30/11/2015# AND #31/12/2015#;
gives me the correct answer. Can someone tell me why the first query doesn't work?
EDIT: Working with date format dd/mm/yyyy. DataType is Date/Time with General Date format.
The reason for your trouble is that Access SQL first tries if the format mm/dd/yyyy makes sense. 01/12/2015 does (reads as 2015-01-12), while 30/11/2015 does not. Next it tries dd/mm/yyyy which will succeed for 30/11/2015 (reads as 2015-11-30). Finally, it will try yyyy/mm/dd.
Thus, as Hans writes:
Many experienced Access developers default to a yyyy-mm-dd to avoid
ambiguity.
However:
If you don't like that, dd mmm yyyy should work.
is doomed to fail in any non-English environment, as mmm will be localized.
So stick to the ISO sequence yyyy-mm-dd or use DateSerial:
WHERE StartDate BETWEEN DateSerial(2015, 12, 1) AND DateSerial(2015, 12, 31);
My project requires I use VB (5 or 6)* to store a date in an SQL Server database. The SQL datetime type includes the time, which I don't want. I'm also aware that VB's representation of a date doesn't mirror that of SQL Server.
So, how can I store a date held in VB's date type in the SQL database, as the datetime at midnight on that date, for example?
Edit: I need to use the date to select rows further down the line, so I can't get away with just truncating it on read.
*I know, I you were me, you wouldn't start from here. But given the constraints, any VB6/MS SQL fiends out there?
VB6 has a DateValue() function which returns the date portion of a Date/Time value, with the time portion "zeroed out". (Note: When the time portion of a date/time variable is "zeroed out", the time would be interpreted as 12:00 AM.)
SQL Server 2008 has new date and time data types. There is the "Date" data type if you don't want to store the time component.
Use the DateTime column and just truncate the time at the presentation level.
Try inserting and updating the date like this:
CAST(FLOOR(CAST(#DateTime AS float)) AS datetime)
We have this in a UDF and it basically strips the time part from a datetime.
In VB you can use the Date() function to return the current date with no time element.
If you an use an ADO Parameter object with a Command object then the OLE DB provider should handle the conversion of a VB Date type to the SQL Server DATETIME value.
In SQL Server (pre SQL 2008 DATE type) you should create a CHECK constraint on the column to ensure it is not possible to add a date with a time element (note I've used an unambiguous language 'safe' format for my DATETIME literals) e.g.
ALTER TABLE MyTable ADD
vb_date DATETIME NOT NULL
CONSTRAINT vb_date__no_time_element
CHECK ((vb_date = DATEADD(DAY, DATEDIFF(DAY, '1990-01-01T00:00:00.000', vb_date), '1990-01-01T00:00:00.000')));
I would just use DateSerial to create the date you need. You pass it a year, month and day and it gives you a date with midnight as the time. You can then use it to pass as a parameter to an ADO command or similar. When you read it, it will have midnight so that isn't a problem. I like it better than DateValue as there is no string conversion. If you really want you can create your own function like DateValue that uses DateSerial.
Function JustTheDatePlease(ByVal dtSource As Date) As Date
JustTheDatePlease = DateSerial(Year(dtSource), Month(dtSource), Day(dtSource))
End Function
If for some reason you aren't using parameterized queries, and you really should have a good excuse for this, you can use the ODBC canonical form of a date in your queries. You just format the date as {d 'yyyy-mm-dd'} for example {d '2009-04-06'}.