This leads into a cte in Oracle 11g:
declare
STARTDATE DATE := '01/01/2017';
;with cte(Accounts) AS (....
This is the error I am getting:
ORA-06550: line 10 column 1 PLS-00103:Encountered the symbol ";"
I need to declare a startdat and it needs to = the date provided.
The snippet you posted doesn't have a begin before tha with, and instead has an extra semicolon.
declare
startdate DATE := DATE '2017-01-01';
begin
with cte(Accounts) AS (....
... complete that statement ... ;
end;
/
You can set the date value as part of the declaration; you shouldn't set it to a string though, as that relies on implicit conversion and NLS settings. I've used a date literal, which has to be in exactly the format shown, YYYY-MM-DD; but to_date() would also work (a literal is simpler though, for a fixed date).
For what I see code, you have to remove the semicolon that is before the statement WITH
I am trying to create a view in oracle which is already defined in DB2,in the DB2 view all date column having cast function , Below i have created a view by taking one date column from the view. Note:COBDATE column having number datatype as for the design. i am getting ORA-00936:missing expression error.
Create View MYVIEWV1 as (Select
A.COBDATE ,
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
(case when (COBDATE = 0)
then CAST(NULL AS DATE)
else
date(SUBSTR(COBDATE,1,4) ||
'-'||SUBSTR(COBDATE,5,2) ||
'-'||SUBSTR(COBDATE,7,2))
end ) as COBDATE2
from MYTBLT1 A;
please suggest how i can convert this to oracle syntax?
The cast isn't the issue, though it isn't really needed. The 'missing expression' error is reported against line 7 column 4, which is the call to the date() function - which doesn't exist in Oracle. It's expecting a date literal to follow the keyword date, not parentheses or function arguments.
You can use the to_date() function instead, with a format model matching the way you're constructing the first argument. You said cobdate is a number but you're treating it as a string so I'll continue to do that implicitly...
create table mytblt1 (cobdate number);
insert into mytblt1 values (20141225);
insert into mytblt1 values (0);
create view myviewv1 as
select cobdate,
case when cobdate = 0
then null -- or with unnecessary cast: cast(null as date)
else
to_date(substr(cobdate,1,4)
||'-'||substr(cobdate,5,2)
||'-'||substr(cobdate,7,2),
'YYYY-MM-DD')
end as cobdate2
from mytblt1;
select * from myviewv1;
COBDATE COBDATE2
---------- -------------------
20141225 2014-12-25 00:00:00
0
desc myviewv1
Name Null Type
-------- ---- ------
COBDATE NUMBER
COBDATE2 DATE
With a cut-down date format model - so you don't have to worry about the - separators - you can simplify it further:
create view myviewv1 as
select cobdate,
case when cobdate = 0
then null -- cast(null as date)
else
to_date(cobdate, 'YYYYMMDD')
end as cobdate2
from mytblt1;
Or you can move the case inside the function call:
create view myviewv1 as
select cobdate,
to_date(case when cobdate = 0 then null else cobdate end, 'YYYYMMDD') as cobdate2
from mytblt1;
Nulls don't need casting. Just use NULL on its own.
case when COBDATE = 0 then NULL
else <some date> end as COBDATE2
Don't need all those brackets either.
I am trying to convert string into date using the following code in PL/SQL:
BEGIN
vfrom := TO_DATE ('20/08/2013', 'dd/mm/yyyy');
vto := TO_DATE ('30/08/2013', 'dd/mm/yyyy');
OPEN L_CURSOR FOR
SELECT DSAT.ORGANIZATION_ID,
APPS.DAW_INV_ORG_NAME (DSAT.ORGANIZATION_ID) ORGANIZATION_NAME,
APPS.DAW_CAT_NAME (MC.SEGMENT4) PRODUCT,
TRUNC (NVL (DSAT.SCH_END_DATE, DSAT.SCH_START_DATE))
TRANSACTION_DATE,
TO_CHAR (NVL (DSAT.SCH_END_DATE, DSAT.SCH_START_DATE),
'MM-YYYY')
MONTH,
DSAT.ITEM_SEGMENTS ITEM_CODE,
DSAT.ITEM_DESCRIPTION,
DSAT.CURRENT_FORECAST_QUANTITY PLAN_QTY
FROM APPS.DAW_SCPDB_ASCP_TPP_V DSAT,
APPS.MTL_ITEM_CATEGORIES MIC,
APPS.MTL_CATEGORIES MC
WHERE NVL (SCH_END_DATE, SCH_START_DATE) BETWEEN '$(vfrom)'
AND '$(vto)'
AND MIC.CATEGORY_SET_ID = 1100000061 --- PLANING CATEGORY
AND MC.CATEGORY_ID = MIC.CATEGORY_ID
AND DSAT.INVENTORY_ITEM_ID = MIC.INVENTORY_ITEM_ID
AND DSAT.ORGANIZATION_ID = MIC.ORGANIZATION_ID
AND DSAT.FORECAST_SET = '$(vForecastSetDPL2)'; --- Need to Update it on Monthly Basis;
END PorductPlanningForecast;
Error occurs as
ORA-01858: a non-numeric character was found where a numeric was expected on line 29
which consists of opening cursor for query. I have checked NSL parameters and set date to the format here in to_Date function, searched all over the internet and yet i cant figure it out. Please help.
In line WHERE NVL(SCH_END_DATE,SCH_START_DATE) BETWEEN '$(vfrom)' and '$(vto)' you have implicit conversion of string '$(vfrom)' to date. That's not going to work.
Assuming that vfrom and vto are declared as date, the line should be like this WHERE NVL(SCH_END_DATE,SCH_START_DATE) BETWEEN vfrom and vto.
I am working on oracle table to pull the data. In one of the query i am using 'where' to filtering between date.
To_Date(VDATU,'DD-MON-YYYY') >= '03-Jun-2012'
AND To_Date(VDATU,'dd-mon-yy') <= '04-Sep-2012'
I am getting error,
ORA-01861: literal does not match format string
I tried using ('dd-mm-yy') but still it is giving the same error. what may the problem??
You are trying to convert VDATU (which is presumably a VARCHAR2) into a date.
In one place you have DD-MON-YYYY and in the other you have dd-mon-yy.
Which one is it? VDATU can not be valid for both.
You're comparing a DATE with a String, try instead:
To_Date(VDATU,'DD-MON-YYYY') >= To_Date('03-JUN-2012','DD-MON-YYYY')
AND To_Date(VDATU,'dd-mon-yy') <= To_Date('04-SEP-2012','DD-MON-YYYY')
In case VDATU is already a date, you shouldn't convert it to_date, all you have to do is:
VDATU >= To_Date('03-JUN-2012','DD-MON-YYYY')
AND VDATU <= To_Date('04-SEP-2012','DD-MON-YYYY')
I have the following query that I am attempting to use as a COMMAND in a crystal report that I am working on.
SELECT * FROM myTable
WHERE to_date(myTable.sdate, 'MM/dd/yyyy') <= {?EndDate}
This works fine, however my only concern is that the date may not always be in the correct format (due to user error). I know that when the to_date function fails it throws an exception.. is it possible to handle this exception in such a way that it ignores the corresponding row in my SELECT statement? Because otherwise my report would break if only one date in the entire database is incorrectly formatted.
I looked to see if Oracle offers an isDate function, but it seems like you are supposed to just handle the exception. Any help would be greatly appreciated. Thanks!!
Echoing Tony's comment, you'd be far better off storing dates in DATE columns rather than forcing a front-end query tool to find and handle these exceptions.
If you're stuck with an incorrect data model, however, the simplest option in earlier versions is to create a function that does the conversion and handles the error,
CREATE OR REPLACE FUNCTION my_to_date( p_date_str IN VARCHAR2,
p_format_mask IN VARCHAR2 )
RETURN DATE
IS
l_date DATE;
BEGIN
l_date := to_date( p_date_str, p_format_mask );
RETURN l_date;
EXCEPTION
WHEN others THEN
RETURN null;
END my_to_date;
Your query would then become
SELECT *
FROM myTable
WHERE my_to_date(myTable.sdate, 'MM/dd/yyyy') <= {?EndDate}
Of course, you'd most likely want a function-based index on the MY_TO_DATE call in order to make this query reasonably efficient.
In 12.2, Oracle has added extensions to the to_date and cast functions to handle conversions that error
SELECT *
FROM myTable
WHERE to_date(myTable.sdate default null on conversion error, 'MM/dd/yyyy') <= {?EndDate}
You could also use the validate_conversion function if you're looking for all the rows that are (or are not) valid dates.
SELECT *
FROM myTable
WHERE validate_conversion( myTable.sdate as date, 'MM/DD/YYYY' ) = 1
If your data is not consistent and dates stored as strings may not be valid then you have 3 options.
Refactor your DB to make sure that the column stores a date datatype
Handle the exception of string to date in a stored procedure
Handle the exception of string to date in a (complex) record selection formula
I would suggest using the first option as your data should be consistent.
The second option will provide some flexibility and speed as the report will only fetch the rows that are needed.
The third option will force the report to fetch every record in the table and then have the report filter down the records.
I have the same problem... an old legacy database with varchar fields for dates and decades of bad data in the field. As much as I'd like to, I can't change the datatypes either. But I came up with this solution to find if a date is current, which seems to be what you're doing as well:
select * from MyTable
where regexp_like(sdate, '[0-1][0-9].[0-3][0-9].[0-9][0-9][0-9][0-9]')
-- make sure it's in the right format and ignore rows that are not
and substr(sdate,7,10) || substr(sdate,1,2) || substr(sdate,4,5) >= to_char({?EndDate}, 'YYYYMMDD')
-- put the date in ISO format and do a string compare
The benefit of this approach is it doesn't choke on dates like "February 30".
Starting from Oracle 12c there is no need to define a function to catch the conversion exception.
Oracle introduced an ON CONVERSION ERROR clause in the TO_DATE function.
Basically the clause suppress the error in converting of an invalid date string (typical errors are ORA-01843, ORA-01841, ORA-011861, ORA-01840) and returns a specified default value or null.
Example of usage
select to_date('2020-99-01','yyyy-mm-dd') from dual;
-- ORA-01843: not a valid month
select to_date('2020-99-01' default null on conversion error,'yyyy-mm-dd') from dual;
-- returns NULL
select to_date('2020-99-01' default '2020-01-01' on conversion error,'yyyy-mm-dd') from dual;
-- 01.01.2020 00:00:00
Solution for the Legacy Application
Let's assume there is a table with a date column stored as VARCHAR2(10)
select * from tab;
DATE_CHAR
----------
2021-01-01
2021-99-01
Using the above feature a VIRTUAL DATE column is defined, that either shows the DATE or NULL in case of the conversion error
alter table tab add (
date_d DATE as (to_date(date_char default null on conversion error,'yyyy-mm-dd')) VIRTUAL
);
select * from tab;
DATE_CHAR DATE_D
---------- -------------------
2021-01-01 01.01.2021 00:00:00
2021-99-01
The VIRTUAL column can be safely used because its format is DATE and if required an INDEX can be set up on it.
select * from tab where date_d = date'2021-01-01';
Since you say that you have "no access" to the database, I am assuming that you can not create any functions to help you with this and that you can only run queries?
If that is the case, then the following code should get you most of what you need with the following caveats:
1) The stored date format that you want to evaluate is 'mm/dd/yyyy'. If this is not the case, then you can alter the code to fit your format.
2) The database does not contain invalid dates such as Feb 30th.
First, I created my test table and test data:
create table test ( x number, sdate varchar2(20));
insert into test values (1, null);
insert into test values (2, '01/01/1999');
insert into test values (3, '1999/01/01');
insert into test values (4, '01-01-1999');
insert into test values (5, '01/01-1999');
insert into test values (6, '01-01/1999');
insert into test values (7, '12/31/1999');
insert into test values (8, '31/12/1999');
commit;
Now, the query:
WITH dates AS (
SELECT x
, sdate
, substr(sdate,1,2) as mm
, substr(sdate,4,2) as dd
, substr(sdate,7,4) as yyyy
FROM test
WHERE ( substr(sdate,1,2) IS NOT NAN -- make sure the first 2 characters are digits
AND to_number(substr(sdate,1,2)) between 1 and 12 -- and are between 0 and 12
AND substr(sdate,3,1) = '/' -- make sure the next character is a '/'
AND substr(sdate,4,2) IS NOT NAN -- make sure the next 2 are digits
AND to_number(substr(sdate,4,2)) between 1 and 31 -- and are between 0 and 31
AND substr(sdate,6,1) = '/' -- make sure the next character is a '/'
AND substr(sdate,7,4) IS NOT NAN -- make sure the next 4 are digits
AND to_number(substr(sdate,7,4)) between 1 and 9999 -- and are between 1 and 9999
)
)
SELECT x, sdate
FROM dates
WHERE to_date(mm||'/'||dd||'/'||yyyy,'mm/dd/yyyy') <= to_date('08/01/1999','mm/dd/yyyy');
And my results:
X SDATE
- ----------
2 01/01/1999
The WITH statement will do most of the validating to make sure that the sdate values are at least in the proper format. I had to break out each time unit month / day / year to do the to_date evaluation because I was still getting an invalid month error when I did a to_date on sdate.
I hope this helps.
Trust this reply clarifies...
there is no direct EXCEPTION HANDLER for invalid date.
One easy way is given below once you know the format like DD/MM/YYYY then below given REGEXP_LIKE function will work like a charm.
to_date() also will work, when invalid_date is found then cursor will goto OTHERS EXCEPTION. given below.
DECLARE
tmpnum NUMBER; -- (1=true; 0 = false)
ov_errmsg LONG;
tmpdate DATE;
lv_date VARCHAR2 (15);
BEGIN
lv_date := '6/2/2018'; -- this will fail in *regexp_like* itself
lv_date := '06/22/2018'; -- this will fail in *to_date* and will be caught in *exception WHEN OTHERS* block
lv_date := '07/03/2018'; -- this will succeed
BEGIN
tmpnum := REGEXP_LIKE (lv_date, '[0-9]{2}/[0-9]{2}/[0-9]{4}');
IF tmpnum = 0
THEN -- (1=true; 0 = false)
ov_errmsg := '1. INVALID DATE FORMAT ';
DBMS_OUTPUT.PUT_LINE (ov_errmsg);
RETURN;
END IF;
tmpdate := TO_DATE (lv_date, 'DD/MM/RRRR');
--tmpdate := TRUNC (NVL (to_date(lv_date,'DD/MM/RRRR'), SYSDATE));
tmpnum := 1;
EXCEPTION
WHEN OTHERS
THEN
BEGIN
tmpnum := 0;
ov_errmsg := '2. INVALID DATE FORMAT ';
DBMS_OUTPUT.PUT_LINE (ov_errmsg || SQLERRM);
RETURN;
END;
-- continue with your other query blocks
END;
-- continue with your other query blocks
DBMS_OUTPUT.PUT_LINE (tmpnum);
END;