as i am using below the condition to change the data_type TO_NUMBER but facing the error while TESTING
ORA-12801: error signaled in parallel query server P01H,
ORA-01722: invalid number
to_number(trunc(CASE WHEN $Aggregation.TP_SYS_NM='CT' THEN $BCRS_TCDR_CT.rwa WHEN $Aggregation.TP_SYS_NM in ('CT1','CT2') THEN $BCRS_TCDR_CT1_CT2.rwa ELSE NULL END))
please help on this issue. thanks in advance.
As long as you are on 12c or above, you can use VALIDATE_CONVERSION or extensions to TO_NUMBER to guard against this, eg
select to_date(created_date, 'dd-mon-yyyy'), ...
from STAGING_SALES
where validate_conversion(
created_date as date, 'dd-mon-yyyy'
) = 1;
which returns 0 or 1 depending on validity, or you can choose a default, eg
select SALES_AMT,
TO_NUMBER(SALES_AMT
DEFAULT -1 ON CONVERSION ERROR) conv_sale
from STAGING_SALES;
More examples and details at this article
https://asktom.oracle.com/Misc/oramag/better-tools-for-better-data.html
I'm getting an error message that tells me I'm entering an invalid number when I try to use a procedure I've made to search through and print records for a given year.
I also need to print records between two dates (e.g. Jan 2016 to Dec 2016) and I have no idea how to do that in the same procedure.
I've tried changing the parameter input type to VARCHAR and DATE, but they don't seem to work either
/*Procedure to search for sales by year*/
CREATE OR REPLACE PROCEDURE SalesReport(
search_year IN NUMBER
)
IS
-- Declare Cursor
CURSOR year_search_cursor IS
SELECT sp_invoice, sp_datesold, sp_saleprice, sp_addncost, sp_deposit, sp_total, sp_id, c_id, v_regno
FROM sales_purchases
WHERE sp_datesold LIKE '%' + search_year;
-- Declare ROW record pointer
sp_year_row year_search_cursor%ROWTYPE;
rec_output VARCHAR2(200); -- Output String
BEGIN
-- Column Headers
DBMS_OUTPUT.PUT_LINE('Invoice_No,'||'Date sold,'||'Sale Price $,'||'AddnCost,'||'Deposit,'||'Total,'||'SP_ID,'||'C_ID,'||'V_RegNo');
-- Fetching data from cursor into variables
FOR sp_year_row IN year_search_cursor LOOP
rec_output:=
sp_year_row.sp_invoice||','||
sp_year_row.sp_datesold||','||
sp_year_row.sp_saleprice||','||
sp_year_row.sp_addncost||','||
sp_year_row.sp_deposit||','||
sp_year_row.sp_total||','||
sp_year_row.sp_id||','||
sp_year_row.c_id||','||
sp_year_row.v_regno;
DBMS_OUTPUT.PUT_LINE(rec_output);
END LOOP;
END;
/
-- Get Input from User
ACCEPT search_year NUMBER PROMPT 'Enter search year: ';
-- Call the UPDATE_INV_SP Procedure and check stock amount status of item
EXECUTE SalesReport(&search_year);
Right now when I try to run the procedure using 'EXECUTE SalesReport(&search_year);' I just get the following error message
Error starting at line : 1 in command -
BEGIN SalesReport(2015); END;
Error report -
ORA-01722: invalid number
ORA-06512: at "19421463.SALESREPORT", line 18
ORA-06512: at line 1
01722. 00000 - "invalid number"
*Cause: The specified number was invalid.
*Action: Specify a valid number.
If your column is date, LIKE will not work. You need to get year out of it
`WHERE EXTRACT(YEAR FROM sp_datesold) = search_year;`
or
`WHERE To_Char(sp_datesold, 'YYYY') = search_year;`
To search range, you can use BETWEEN
`WHERE To_Char(sp_datesold, 'YYYY') BETWEEN v_year1 and v_year2;`
These are not necessarily optimized but you get the idea
This is better. Note, I put strings there just for show. In reality, these should be dates come from parameters - important - no time part for date1 and date2
Date1 date := to_date('01/01/2016', 'MM/DD/YYYY');
Date2 date := to_date('12/31/2016', 'MM/DD/YYYY') + 1;
`WHERE sp_datesold >= date1 AND sp_datesold < date2;`
I want to execute this sql query on a hive table:
select * from sampleDB.sampleTable
where sampleDate>=(select convert(DATE, dateadd(MONTH,-6,getdate())));
But I am getting this error: Error while compiling statement: FAILED: parse exception line 1:64 cannot recognize input near 'select' 'convert' '(' in expression specification (state=42000,code=40000)
Can someone help me understand how this can be achieved? Basically I want to filter on date say 6 months from current date.
Thanks!
Hive do not supports only >= in sub query it support only below type of sub query
Scalar subqueries
IN subqueries
EXISTS subqueries
you can achieve the same with daenter link description hereteformate
select * from sampleDB.sampleTable
where sampleDate>= date_format(current_date - interval '7' day,'%Y-%m-%d') ;
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;
I am getting a ORA-00907: missing right parenthesis from the following code below
dbQuery:= TQuery.Create(nil);
dbQuery.DatabaseName:= dbMain.DatabaseName;
with dbQuery do
begin
SQL.Add('select payee_address_zip, EXTRACT(WEEKDAY FROM check_date) as DOW, ');
SQL.Add('(cmcl_bank_cleared - check_date) as DateDiff from AP_Master ');
SQL.Add('where (cmcl_bank_cleared is not null) AND ((cmcl_bank_cleared - check_date) >=:DaysParam)');
SQL.Add('order by payee_address_zip, DOW, DateDiff');
try
ParamByName('DaysParam').AsInteger:= days_param_int;
Open;
//do something else here
except on E:EDatabaseError do
begin
raise ECustomException.create('Error opening query for step 1 of computing Float Factors!');
end;//except
end; //try
end; //with
dbQuery.Free;
Can someone tell me what is going on? I can't seem to see that i have left out a parenthesis, and this SQL works just fine against a Interbase test database. However, when moving it to a clients oracle database, it crashes, with the error above.
Let's check with SQL*Plus, so you can see exactly at which place the parser expects a right parenthesis:
SQL> create table ap_master(payee_address_zip,check_date,cmcl_bank_cleared)
2 as
3 select 1,sysdate,sysdate+1 from dual
4 /
Table created.
SQL> var DaysParam number
SQL> exec :DaysParam := 1
PL/SQL procedure successfully completed.
SQL> select payee_address_zip
2 , EXTRACT(WEEKDAY FROM check_date) as DOW
3 , (cmcl_bank_cleared - check_date) as DateDiff
4 from AP_Master
5 where (cmcl_bank_cleared is not null)
6 AND ((cmcl_bank_cleared - check_date) >=:DaysParam)order by payee_address_zip, DOW, DateDiff
7 /
, EXTRACT(WEEKDAY FROM check_date) as DOW
*
ERROR at line 2:
ORA-00907: missing right parenthesis
So there is something with your EXTRACT function. This is the relevant piece of documentation about the EXTRACT (datetime) function:
http://download.oracle.com/docs/cd/E11882_01/server.112/e17118/functions059.htm#sthref1117
It doesn't mention your WEEKDAY keyword. You can get the weekday by using the TO_CHAR function though. I don't know which date format element you want exactly. I guess 'D' or 'DAY'. You can look them up here:
http://download.oracle.com/docs/cd/E11882_01/server.112/e17118/sql_elements004.htm#CDEHIFJA
If you change the EXTRACT expression and replace it with a TO_CHAR, it will work:
SQL> select payee_address_zip
2 , to_char(check_date,'d') as DOW
3 , (cmcl_bank_cleared - check_date) as DateDiff
4 from AP_Master
5 where (cmcl_bank_cleared is not null)
6 AND ((cmcl_bank_cleared - check_date) >=:DaysParam)order by payee_address_zip, DOW, DateDiff
7 /
PAYEE_ADDRESS_ZIP D DATEDIFF
----------------- - ----------
1 4 1
1 row selected.
Regards,
Rob.
It looks like you're missing a space on the end of this line:
SQL.Add('where (cmcl_bank_cleared is not null) AND ((cmcl_bank_cleared - check_date) >=:DaysParam)');