ORA-00920: invalid relational operator - sql

In a database, I am trying to pull information that is later than a specified date. I should note beforehand that the date is in an odd format: YYYYMMDDHH24MISS## where ## is a two letter string which defines something useless to my query. Thus, I am using substr to just remove them.
My query, below, throws the following error, and I canot find out why:
[Error Code: 920, SQL State: 42000] ORA-00920: invalid relational
operator
My Query:
SELECT *
FROM table_name
WHERE to_date(substr(COLUMN_NAME,1,14), 'YYYYMMDDHH24MISS')) >=
to_date('MIN_DATE', 'YYYYMMDDHH24MISS')
I have checked to make sure the dates are being defined correctly, and they are.
Example of what I have used for MIN_DATE is: 20140101000000

You have an extra parenthesis at the end of the first to_date

You get this error in Oracle when you are missing a comparison operation, such as = -- as John Maillet already noted.
My concern is the second part of the where clause:
where to_date(substr(COLUMN_NAME, 1, 14), 'YYYYMMDDHH24MISS') >=
to_date('MIN_DATE', 'YYYYMMDDHH24MISS')
You have MIN_DATE in single quotes. This is interpreted as a string with eight letters in it, starting with 'M' and ending with 'E'. This is not interpreted as a variable. Presumably you mean:
where to_date(substr(COLUMN_NAME, 1, 14), 'YYYYMMDDHH24MISS') >=
to_date(MIN_DATE, 'YYYYMMDDHH24MISS')
You should only use single quotes for string and date constants.
I should add that you should be able to do this comparison without having to convert to dates:
where left(COLUMN_NAME, 14) = MIN_DATE

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')

Same query works fine in a certain database but throws error in different database

I am trying to fetch the year from 'MON-YY' format and then concatenating the fetched year with '01-JUN' . I used to_date to forcefully convert 'string' ('01-JUN-17') to 'date' type
The below code works fine in a particular database for eg db_1
select to_date('01-JUN-'||(EXTRACT(YEAR FROM to_date('MAY-17','mon-yy'))) ) AS YEAR_START_DATE from dual;
returns :
01-JUN-17
But in db_2 the same code throws the below error :
ORA-01858: a non-numeric character was found where a numeric was expected
01858. 00000 - "a non-numeric character was found where a numeric was expected"
*Cause: The input data to be converted using a date format model was
incorrect. The input data did not contain a number where a number was
required by the format model.
*Action: Fix the input data or the date format model to make sure the
elements match in number and type. Then retry the operation.
Can someone please help ?
'01-JUN-' || EXTRACT(YEAR FROM to_date('MAY-17','mon-yy'))
Will generate a string like '01-JUN-2017'
The problem occurs when you try to use TO_DATE( datestring, format_model ) without specifying a format model. In this case the query will use the NLS_DATE_FORMAT session parameter.
You can find the value for this using:
SELECT VALUE
FROM SYS.NLS_SESSION_PARAMETERS
WHERE PARAMETER - 'NLS_DATE_FORMAT';
If this does not match the format you specify then it will raise an exception.
You should explicitly specify the format model (and the language):
SELECT TO_DATE(
'01-JUN-'||EXTRACT(YEAR FROM to_date('MAY-17','mon-yy','NLS_LANGUAGE="ENGLISH"')),
'dd-MON-YYYY',
'NLS_LANGUAGE="ENGLISH"'
) AS YEAR_START_DATE
FROM DUAL;
Or you could use:
SELECT ADD_MONTHS(
TRUNC(
TO_DATE( 'MAY-17', 'MON-YY', 'NLS_LANGUAGE="ENGLISH"' ),
'YY'
),
5
) AS YEAR_START_DATE
FROM DUAL;
You are missing a date format for your first to_date('01-JUN-'..) function. The date format for one database is probably DD-MON-YYYY but it could be DD-MM-YYYY in the other database.
After adding the date format your query looks like this:
select to_date('01-JUN-' || (extract(year from to_date('MAY-17', 'mon-yy'))),'DD-MON-YYYY') as year_start_date
from dual;
It's good practise to always specify a format when converting dates from and to strings.

Convert date to specific format using Postgresql

I am needing to convert records where the TEXT values look like this using Postgresql:
26-AUG-2015
to:
2015-08-26
I'm not sure what version of Postgresql exists on the vendor server but I tried to do a select statement using:
SELECT to_char(sle.log_field1, 'YYYY-MM-DD')
FROM student_log_entires sle;
But I'm getting this error:
Error: SQL Error: SQLSTATE[42883]: Undefined function: 7 ERROR: function to_char(text, unknown) does not exist LINE 25: AND to_char(sle.log_field1, 'YYYY-MM-DD') >=... ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts.
I did also try:
SELECT to_date(sle.log_field1, 'YYYY-MM-DD')
FROM student_log_entries sle
But I got this error:
Error: SQL Error: SQLSTATE[22007]: Invalid datetime format: 7 ERROR: invalid value "[E] " for "YYYY" DETAIL: Value must be an integer. Query: SELECT to_date(sle.log_field1, 'YYYY-MM-DD') FROM student_log_entries sle
Any suggestions/direction would be appreciated. Thanks.
This assumes that lc_time is set to English:
SELECT to_char(to_date('26-AUG-2015', 'DD-MON-YYYY'), 'YYYY-MM-DD');
to_char
------------
2015-08-26
(1 row)
You can convert the value to a date and then back to a string:
select to_char(to_date('26-AUG-2015', 'DD-MON-YYYY'), 'YYYY-MM-DD')
Under many circumstances, processing the value as a date is probably sufficient.
Your approach doesn't work because the value is apparently already stored as a string, so converting it back to a string with a date format doesn't make sense.
EDIT:
You may be able to get by using a simple regular expression:
select (case when col ~ '^[0-9]{2}[-][A-Z]{3}[-][0-9]{4}$'
then to_char(to_date('26-AUG-2015', 'DD-MON-YYYY'), 'YYYY-MM-DD')
end)
Of course, if the formatting errors are more subtle, then a more complex regular expression would be needed.
try this,
SELECT to_char(sle.log_field1, 'YYYY-MM-DD') FROM student_log_entires sale;

Why are these NVL() statements wrong in SQL?

SELECT inv_no,NVL2(inv_amt,inv_date,'Not Available')
FROM invoice;
SELECT inv_no,NVL2(inv_amt,inv_amt*.25,'Not Available') FROM invoice;
getting
ORA-01858: a non-numeric character was found where a numeric was expected
ORA-01722: invalid number
respectively
Please suggest what are the datatypes I can give in expr1 and expr2.
Also Please tell me how this is right?
SELECT inv_no,NVL2(inv_date,sysdate-inv_date,sysdate)
FROM invoice
The 2nd and 3rd parameters to NVL2 should be the same datatype. So, assuming inv_date is a DATE, you'd need to have that as a varchar2 like;
SELECT inv_no, NVL2(inv_amt, to_char(inv_date, 'dd-mon-yyyy hh24:mi:ss'), 'Not Available') FROM ...
or whatever format string you wanted. Otherwise Oracle will convert the 3rd parameter 'Not Available' to match the 2nd parameter's data type. This will try to convert 'Not Available' to a date and crash.
Similarly in the 2nd example, you have to convert the inv_amt*.25 to a char viato_char, e.g. to_char(inv_amt*.25).
Your first 2 examples attempt to have a date / numeric and text results for the same field. This will cause an error when Oracle attempts to convert this text to either types. You'll need to use the to_char(field) function on the date / numeric fields to convert them to text.
Lastly a date is in fact a number added to a databases base date. For example a date is a number of base day and the decimal it has is the ratio of a day, e.g. 0.5 is 12 hours, and the database has a base date, e.g. 01-Jan-1900 or 01-Jan-2000. This is why when you do date - date the result is a number and a date can also be represented as a number.
Refer to: https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions106.htm
The 2nd argument should be either character or numeric. The 2nd argument gives datatype to which the 3rd argument will be implictly converted. So:
1. The first one SELECT inv_no,NVL2(inv_amt,inv_date,'Not Available') FROM invoice; is incorrect as you cannot have DATE as a 2nd argument.
The same way:
SELECT NVL2(NULLIF(1, 1), SYSDATE, 'A') FROM DUAL; -- FAILS;
SELECT NVL2(NULLIF(1, 0), SYSDATE, 'A') FROM DUAL; -- FAILS;
SELECT NVL2(NULLIF(1, 1), 'A', SYSDATE) FROM DUAL; -- PASS; returns SYSDATE (as char datatype)
SELECT NVL2(NULLIF(1, 0), 'A', SYSDATE) FROM DUAL; -- PASS; returns 'A';
2. The second is invalid too: SELECT inv_no,NVL2(inv_amt,inv_amt*.25,'Not Available') FROM invoice; Oracle tries to implicitly convert 3rd argument to the datatype of the 2nd arugment, meaning it tries to convert 'Not available' to numeric value.
It will work when you swap 2nd and 3rd argument:
SELECT inv_no,NVL2(inv_amt,'Not Available',inv_amt*.25) FROM invoice;
inv_amt*.25 will be implicitly converted to character data; This example is useless as it will get you NULL*.25 making it NULL.
What you can do however is you can make both parameters as characters by converting numeric result to character:
SELECT inv_no,NVL2(inv_amt,TO_CHAR(inv_amt*.25), 'Not Available') FROM invoice;
It will make some sense particularly when you want to display currency.
3. The third one is more complex
The only way I can explain is that the 2nd argument gets converted to character before dealing with the third one. That way the third one will get converted to characters too. This would make sense given the two cases:
SELECT NVL2(2, SYSDATE - TO_DATE('10-JAN-83'), SYSDATE) from dual; -- PASSES
SELECT NVL2(2, 2.2, SYSDATE) from dual; -- FAILS.
Finally: I would advise to stick to Oracle's documentation and use explicit conversion.

Errors while trying to cast/convert VARCHAR to DATETIME in ANSI SQL

I have a column in a table where timestamps have been stored in VARCHAR format, but I need to compare these against a column of DATETIME values from another table to find time intervals, so I want to either cast or convert the VARCHAR timestamps to DATETIME. However, both casting and converting are giving me problems.
The format of the VARCHAR timestamp looks like this: "29/07/2012 01:53:36 +12".
Using the query:
SELECT CAST(event_timestamp AS datetime) FROM the_table
produces ERROR: date/time field value out of range: "29/07/2012 01:53:36 +12".
Using the query:
SELECT CONVERT(datetime, event_timestamp, 131) from the_table;
produces
ERROR: syntax error at or near ","
LINE 1: select CONVERT(datetime, event_timestamp, 131) from the_tab...
^ (note: this is pointing at the first comma).
The error with CONVERT actually happens even if you use a generic function such as getdate() for the data source. This db uses ANSI SQL-92 (or so I'm told). Could anyone please help me out with this?
This seems really painful, but the following should work:
select dateadd(hh, cast(right(tv, 3) as int),
CONVERT(datetime, left(tv, 10), 103)+CONVERT(datetime, substring(tv, 12, 8), 108)
)
from (select '29/07/2012 01:53:36 +12' as tv) t
I've never added datetime's before, but this just worked on SQL Server 2008.
Why can't SQL Server just support a flexible notation built around yyyy, mm, mmm, dd and so on?
The actual database is Aster Data, which is based on Postgres (as are most recent database engines). In this database, you would use to_timestamp(). See the documentation here http://www.postgresql.org/docs/8.2/static/functions-formatting.html. The call would be something like:
to_timestamp(val, 'MM/DD/YYYY HH:MI:SS tz') -- not sure if this gets the +12
There are no ANSI functions for date conversion, so each database does its own. Even string functions vary among databases (substr? substring? charindex? instr? location?), so there is no ANSI way to do this.
You are using the wrong syntax, try:
CONVERT(varchar(X), datetimeValue, 131)
Where X is the total number of characters desired.
You will then be able to search for a match with datetimeValue and event_timestamp, assuming each value share the same structure. This will allow you to match string against string.
If I'm not mistaken the standard (ANSI SQL) CAST operator always expect time/date/timstamp literals in ISO format ('YYYY-MM-DD')
But according to the manual for Teradata V12 (can't test it), the format of the CAST operator is
CAST(character_expression AS TIMESTAMP timestamp_data_attribute)
with date_data_attribute being a character value plus an optional FORMAT specifier.
So in your case this would probably be:
cast(event_timestamp AS TIMESTAMP FORMAT 'MM/DD/YYYY HH:MI:SS Z');
I'm not entirely sure about the format definition though. You'll probably need to adjust that
Btw: CONVERT isn't a standard SQL function. It's SQL Server specific.