Date Formats in SQL - sql

((SELECT ES.MCH_POS
FROM IFSAPP.EQUIPMENT_SERIAL ES
WHERE ES.CONTRACT = W.CONTRACT
AND ES.MCH_CODE = W.MCH_CODE), 'yyyy/mm/dd') as SALE_DATE
When I run this code an error is occurred as ORA-00907: missing right parenthesis

ORA-00907: missing right parenthesis
This is a syntax error. Occasionally it really does mean we have a unpaired left parenthesis. More often it means we have made a bloomer, and we have a keyword or expression where the compiler expected a closing ). Sometimes it just points to a typo.
, 'yyyy/mm/dd' is a format mask, used in casting a string to a date or a date to string. However, your snippet has no TO_DATE() or TO_CHAR() function, so I'm guessing that's your problem. You have a format mask where the compiler thinks there should be just a ).
With just a subquery to go on it's hard to be sure but probably what you want is something like this:
(SELECT to_char(ES.MCH_POS, 'yyyy/mm/dd') as SALE_DATE
FROM IFSAPP.EQUIPMENT_SERIAL ES
WHERE ES.CONTRACT = W.CONTRACT
AND ES.MCH_CODE = W.MCH_CODE)
If this is not the exact solution you require and doesn't help you get to it please edit your question to include more details regarding the problem you are trying to solve.

In Oracle you need the to_char() function
TO_CHAR(date-value,'date-format-mask')
From your code snippet it should look more along these lines 9I think):
select ....
, to_char((SELECT ES.MCH_POS
FROM IFSAPP.EQUIPMENT_SERIAL ES
WHERE ES.CONTRACT = W.CONTRACT
AND ES.MCH_CODE = W.MCH_CODE
AND rownum = 1), 'yyyy/mm/dd') as SALE_DATE
i.e. the correlated subquery returns one date value, and that date value is then formatted as yyyy/mm/dd
nb: I threw in the and rownum = 1 because as you see it above, that correlated subquery MUST only return a single date value.

Related

Why I get error when using TO_DATE() while converting from VARCHAR to Date data type

I am currently stuck in error which I don't understand clearly.
ORA-01843: not a valid month
01843. 00000 - "not a valid month"
*Cause:
*Action:
So far I check a couple of post here in Stackoverflow but doesn't help me so much.
I have query something like
SELECT * FROM (
SELECT uta.StartDate,uta.EndDate
FROM user_timesheets_absence uta
LEFT JOIN users u
ON u.UserID = uta.UserID
AND uta.Approved = '0'
AND
((
'2020-01-30' >= TO_DATE(uta.StartDate,'YYYY-MM-DD')
AND
'2020-02-06' <= TO_DATE(uta.EndDate,'YYYY-MM-DD')
)
OR
(
'2020-01-30' <= TO_DATE(uta.StartDate,'YYYY-MM-DD')
AND
'2020-01-30' >= TO_DATE(uta.StartDate,'YYYY-MM-DD')
))
--GROUP BY uta.UserAbsenceID
UNION
SELECT ut.DATE_ AS StartDate,
ut.DATE_ AS EndDate
FROM user_timesheets ut
INNER JOIN moments m ON
m.UserTimesheetsID = ut.UserTimesheetsID
WHERE
TO_DATE(ut.DATE_,'YYYY-MM-DD') BETWEEN '2020-01-21' AND '2020-01-30' + SYSTIMESTAMP + 1
AND ut.user_id = 1
) a
Here is the problem which StartDate and EndDate filled are VARCHAR2
I try using 'TO_TIMESTAMP' and try to change format to YYYY/MM/DD but doesn't work.
I have to be honest that I don't have any idea so far what I made wrong here.
Where I made mistake ? What is wrong here ?
UPDATE
As GMB from answer said that using validate_conversion() gives meall invalid date strings
Result
And so far from query above, when I run it I get following error
ORA-01861: literal does not match format string
01861. 00000 - "literal does not match format string"
*Cause: Literals in the input must be the same length as literals in
the format string (with the exception of leading whitespace). If the
"FX" modifier has been toggled on, the literal must match exactly,
with no extra whitespace.
*Action: Correct the format string to match the literal.
Some of the strings in your column are invalid dates. Starting version 12.2, it is easy to exhibit them with function validate_conversion() clause of to_date(). The following query gives you all invalid date strings:
select date_
from user_timesheets
where validate_conversion(date_ as date, 'YYYY/MM/DD') = 0
You can then fix your data.
You should consider using the date datatype to store dates, so that integrity is enforced at the time when the data is written.
In the meantime, let me suggest, however, to optimize the filtering logic: the formats of your strings make it possible to use direct filtering (without prior conversion to a date): this is more efficient, since it does not requires converting the entire column before filtering (on says that the predicate is SARGeable). Typically, you would replace something like:
to_date(uta.startdate,'yyyy/mm/dd') <= '2020-01-30'
With:
ut.startdate <= '2020/01/30'
Or if you are filtering agains the current system date:
ut.startdate <= to_char(sysdate, 'YYYY/MM/DD')
Not all startdate and enddate columns have values in YYYY/MM/DD format or - if they do - they are invalid.
For example: values like 2020/A8/43 or ab3f/xy/2i or 2020/15/02 and similar are invalid.
Error says that MM part of those strings isn't in range between 01 and 12.
First you should be storing date values using date, not strings. One possibility is that these actually are dates and you don't need to reconvert them. Without sample data, it is hard to say. But you should put your effort into fixing the data.
Second, date constants in Oracle should look like:
DATE '2020-01-30'
So:
DATE '2020-01-30' >= TO_DATE(uta.StartDate,'YYYY/MM/DD')

Using Where Clause with Dates When Reading SQL Query in R

I am attempting to query an Oracle datebase from R using the SQL function found here.
When I complete an easy query, such as
'SELECT * FROM TABLE_1'
the query executes fine. However, when I add a conditional date statement to the query, such as
'SELECT * FROM TABLE_1 WHERE START_DT BETWEEN '01-JUL-2018' AND '30-JUN-2019'
I get the following error message:
Error in .oci.SendQuery(conn, statement, data = data, prefetch =
prefetch, : ORA-00904: "30-JUN-2019": invalid identifier
Any idea how I can fix this?
The exact error appears to be that you didn't escape the single quotes you placed around the date literals in your R query string. But, fixing that still leaves the problem that your date literals are invalid for Oracle. I recommend using this:
sql <- "SELECT * FROM TABLE_1 WHERE START_DT BETWEEN DATE '2018-07-01' AND DATE '2019-06-30'"
You could also use the TO_DATE function, e.g. TO_DATE('01-JUL-2018', 'DD-MON-YYYY'), but this is a bit harder to read than using the DATE keyword.

CDate makes DateAdd formula fail

I hope I will be forgiven for transgressing the rules ever so slightly by asking for a reason, rather than a solution.
I have the following code:
INSERT INTO destinationTable (RecordMonth, ...)
SELECT t1.Expr1, ...
FROM
(
SELECT
CDate(Format("01-" & Right([t1].[Year-Month],2) & "-" & Left([t1].[Year-Month],4),"dd/mm/yyyy")) AS Expr1,
/* ...other fields with no bearing... */
FROM tcsvMonthData AS t1
)
WHERE t1.Expr1 >= DateAdd("m",-6,(SELECT MAX(Expr1) FROM t1))
[Year-Month] in t1 is a varchar-type field.
This script fails, Access gives the following error message: "Data type mismatch in criteria expression."
If I remove the CDate block the script will work. Happy to have found the answer but I don't understand why the error occurs in the first place. CDate constrains a field to a date type. After format the field should be a date type already, so CDate is redundant, but it should not harm (not in my head, at least). Also, as far as I know DateAdd unlike say, Year, does not convert the input field to a string, it should maintain a date type. So what is going on here?
EDIT:
Year-Month describes the month the record occurred in and it looks like this: 2017-11. It is a varchar type and the goal is to have it as a proper datetime field in dd/mm/yyyy format where each month is represented by the first day of that month. So May is 01/05/2018 etc.
You are seriously overcomplicating this. CDate is all you need:
CDate([t1].[Year-Month]) AS Expr1
Edit:
To accept Null values, either filter these out, or use CVDate to either pass Null on:
CVDate([t1].[Year-Month]) AS Expr1
or supply a default value using Nz:
Nz(CVDate([t1].[Year-Month]), Date()) AS Expr1
I have found a solution in sql server please use cdate in place of cast for ms access.
select cast(format(cast('01-' + left('07/23/2018',2) + '-' + right('07/23/2018',4) as date),'dd/MM/yyyy') as date) AS Expr1
change the static date with your column.
It’s been a long time since I have had to use Access but I think the problem isn’t with your use of CDate() but rather the use of Format() on the internal string. Format() needs to operate on a date, but you are giving it a string. Because Format is failing, the surrounding CDate() is failing as well.
You need to use CDate () before Format() like this:
Format(CDate ("01-" & Right([t1].[Year-Month],2) & "-" & Left([t1].[Year-Month],4),"dd/mm/yyyy")) AS Expr1,
You may need to do some tweaking to get that to run but the basic idea should work.
The rejected answer below works because Cast As Date (which is functionally equivalent to CDate) is used both before and after Format() so Format() is being passed a Date. The 2nd Cast in that example is redundant.

oracle sql - a non-numeric character was found where a numeric was expected

I know there are loads of postings regarding fixing this error but, I'm just not understanding it!
val_strg1 value is 01.04.2016. I want to use this and not show lines where this date is older than current date, (i.e. and trunc(sysdate) < dv.val_strg1).
But, even though I have used a to_date format, I still get the a non-numeric character was found where a numeric was expected error?
I have tried several to_date formats;
to_date(val_strg1,'DDMMYYYY'), to_date(val_strg1,'DD-MM-YYYY')
The following gives me a 'not a valid month' error?
to_date(val_strg1,'DD-MON-YYYY')
My script...
select val_strg, val_strg1, to_date(val_strg1,'DDMMYYYY')
from sd_domainval_org
where name = 'HYPERCARE_CUNR'
order by sort_no
How can I use the val_strg1 as a date?
It seems you are using a text column (e.g. VARCHAR2) for the date. And you are saying that
to_date(val_strg1, 'DD.MM.YYYY')
results in an error. So you have a value in that column that does not match the pattern. Here is a query to find such invalid entries:
select *
from domainval
where name = 'HYPERCARE_CUNR'
and not regexp_like(val_strg1, '^[[:digit:]]{2}\.[[:digit:]]{2}\.[[:digit:]]{4}$');
You can then correct the wrong entries, but a better solution would of course be not to store dates in string columns at all. Use date columns instead, so as to not have such issues.
if your string date val_strg1 is in the form 'DD.MM.YYYY' (i.e. '01.04.2016'), then you have to use to_date(val_strg1,'DD.MM.YYYY');
for example: Select to_date('01.04.2016','DD.MM.YYYY') from dual;
If you have errors again, probably you have a string in the recordset that is not in a valid form for the to_date function (check the values in the val_strg1 column).
Bye,
Igor
I found an answer...
and trunc(sysdate) < to_date(regexp_substr(val_strg1, '^[[:digit:]]{2}\.[[:digit:]]{2}\.[[:digit:]]{4}$'),'DD.MM.YYYY')
...seems to work OK.
you have to tune formating string to exactly match your date structure
in this case
select val_strg, val_strg1, to_date(val_strg1,'DD.MM.YYYY')
from sd_domainval_org
where name = 'HYPERCARE_CUNR'
order by sort_no;

Oracle: between dates statement gives error 'not valid month'

I'm not sure what I'm doing wrong here. I'm trying to build an oracle query that I will be executing from my php project via oci. I need to select all records between a specific date range.
In trying to get the syntax down, I wrote out this test query:
SELECT * FROM SHIPPED
WHERE user_seq_id = 381 AND
LOT_DATE BETWEEN TO_DATE('05/27/2014', 'MM/DD/YYYY')
AND TO_DATE('06/03/2014','MM/DD/YYYY');
This syntax seems like it should work but it's not. I'm definitely not an oracle developer so I'm positive I"m misunderstanding something. When I've looked at similar posts I haven't found anything that would point to what I'm doing wrong.
This is a rather tricky error. The problem would occur if LOT_DATE were stored as a character string rather than a date -- and the string contained invalid data.
By explicitly converting the right hand side of the comparison to dates, the comparison is attempted by converting the field to a date. And there is an error.
The fix is to fix the data in the field. if something is in a field called "date", then it should probably have a date data type.
For identifying unsupported string value for date - You can create a PL/SQL function which accepts string and validate for correct date format, sample of function:
CREATE OR REPLACE FUNCTION VERIFY_DATE(v_date IN VARCHAR2) RETURN NUMBER IS
v_date1 DATE;
BEGIN
select to_date(v_date) into v_date1 from dual;
RETURN 1;
Exception WHEN Others THEN
RETURN 0;
END;
Now, identify rows which are having invalid string value for which you should correct to run your query:
select * from
(
select VERIFY_DATE(LOT_DATE) DateVerified,s.* from SHIPPED s
)
where
DateVerified=0