How can I hardcode date into Oracle query in SSIS - oracle

I am very new to Oracle database and I am trying to hardcode the date (2020-06-30 0:00:00) into the query below, however I get the following errors
[valsys_TIMESERIES_VALUE [37]] Error: SSIS Error Code DTS_E_OLEDBERROR. An OLE DB error has occurred. Error code: 0x80040E14.
An OLE DB record is available. Source: "OraOLEDB" Hresult: 0x80040E14 Description: "ORA-12801: error signaled in parallel query server P006
ORA-01821: date format not recognized
ORA-02063: preceding 2 lines from VALSYS".
An OLE DB record is available. Source: "OraOLEDB" Hresult: 0x80004005 Description: "ORA-12801: error signaled in parallel query server P006
ORA-01821: date format not recognized
ORA-02063: preceding 2 lines from VALSYS".
"SELECT TS_ID,DATE_UTC,VALUE,CASE WHEN VALUE = 0 THEN '0' ELSE TO_CHAR(VALUE) END VALUE_CONV ,SUBSTITUTE_VALUE
,CASE WHEN SUBSTITUTE_VALUE = 0 THEN '0' ELSE TO_CHAR(SUBSTITUTE_VALUE) END SUBSTITUTE_VALUE_CONV ,MANUAL_VALUE, CASE WHEN MANUAL_VALUE = 0 THEN '0' ELSE TO_CHAR(MANUAL_VALUE) END MANUAL_VALUE_CONV,FEASIBLE
,VERIFIED,APPROVED,VALID_FROM,VALID_UNTIL,LAST_EXPORT,DAY_CET,COMPUTED,MARKER,TASK_UNIT_ID FROM \""+ #[$Project::Oracle_Valsys_Schemaname] + "\".\"VALSYS_TIMESERIES_VALUE\"
WHERE VALID_FROM > to_timestamp('"+ #[User::PreLET] + "', '2020-06-30 0:00:00') "

The second parameter of to_timestamp is a format mask, e.g. 'yyyy-mm-dd hh24:mi:ss'
This is a sample usage
select
to_timestamp('2020-06-30 00:00:00', 'yyyy-mm-dd hh24:mi:ss') tst
from dual;
TST
-----------------------------
30.06.2020 00:00:00,000000000

Related

Power BI Oracle OLEDB need a where clause to get the first day of the year

using Power BI to connect to Oracle database server 19c using this connection: provider=OraOLEDB.Oracle.1;data source=gencdbp.domain.pri:1521/GAEN
I need a SQL statement that limits the rows so I don't have to hardcode it.
This works:
select * from aTable where DateCreated >= TO_Date('01/01/2022', 'MM/DD/YYYY')
I have tried the Year function and TRUNC function. Both of these gives me an error:
DateCreated is a Timestamp(6). These do not work:
where DateCreated >= trunc(sysdate, 'YEAR')
where trunc(DateCreated, 'YEAR') = trunc(sysdate, 'YEAR')
YEAR(DateCreated) = YEAR(sysdate)
These all give me this error:
ORA-00904: "YEAR": invalid identifier
Details:
DataSourceKind=OleDb
DataSourcePath=data source=gencdbp.domain.pri:1521/GAEN;provider=OraOLEDB.Oracle.1
Message=ORA-00904: "YEAR": invalid identifier
ORA-00904: "YEAR": invalid identifier
ErrorCode=-2147217900
I don't know tool you use (Power BI), but - have a look at the following example:
Sample table that contains a column whose datatype matches the one you specified:
SQL> create table test (datecreated timestamp(6));
Table created.
Insert sample value:
SQL> insert into test values (systimestamp);
1 row created.
OK, let's now try something you said doesn't work (but raises ORA-00904):
SQL> select * from test where trunc(datecreated, 'year') = trunc(sysdate, 'year');
DATECREATED
---------------------------------------------------------------------------
11-MAY-22 09.47.30.544000 PM
It works OK for me.
Another option might be the extract function:
SQL> select * from test where extract(year from datecreated) = extract(year from sysdate);
DATECREATED
---------------------------------------------------------------------------
11-MAY-22 09.47.30.544000 PM
So, are you sure you really used code you posted? Because, that's the error which suggests that there's no column named year in that table. To simulate it, I removed single quotes for year (which is - for the to_char function - format model):
SQL> select * from test where trunc(datecreated, year) = trunc(sysdate, year);
select * from test where trunc(datecreated, year) = trunc(sysdate, year)
*
ERROR at line 1:
ORA-00904: "YEAR": invalid identifier
SQL>
Right; here it is, ORA-00904.

ORA-01882: timezone region not found ORA-02063: line precediendo a DBLink

An error occurred accessing info in DataBase, the database is Oracle. I access the database from a Weblogic 12.
The last time I had the same error with timezone. I fixed using the following (like argument in Weblogic 11):
-Duser.timezone=GMT
This time I get this error:
java.sql.SQLDataException: ORA-01882: timezone region not found ORA-02063: line precediendo a DBLink
Here is the SQL:
SELECT A.DEPT, A.EMP_NAME, A.EMP_LOC, A.LAST_NAME, A.ADDRESS_1, A.ADDRESS_2, A.ADDRESS_3, A.ADDRESS_4, A.CONTROL_NUM, A.EMP_SSID, A.PEN_DATE, B.EMP_LEVEL_ACCESS, C.CONF_NUM, replace(A.EX_SALARY, ' ', '') as EX_SALARY, replace(A.EX_SAL_CODE, ' ', '') as EX_SAL_CODE, replace(A.BIRTHDATE, ' ', '') as BIRTHDATE FROM EMP_W2_INFO_TBL A, EMP_LEVEL_ACCESS_VW B, FILING_CONF_TBL C WHERE A.EMP_NUM = 'XXXXX' AND A.TAX_YEAR = '2016' AND A.EMP_NUM = B.EMP_ID AND A.TAX_YEAR = C.TAX_YEAR (+);
I validate DBLink is not corrupted checking the connectiong.

Oracle DB Ora-01839: date not valid for month specified. 29-02-2016 leap year

We all know today is a special day. Its the 29th of February 2016 of a leap year.
We receive an error message from some tables in our Oracle DB. The error is:Oracle ORA-01839: date not valid for month specified.
For example a simple select where the error occurs:select * from table where table_date > sysdate -0.1;
For other tables this select makes no problem, just for some of the tables.
Is there a way to fix this issue? Because we are not able to use many tables today.
We are using Oracle 12c.
After intensive research, its clear why some of our selects does not work today. The error is caused by the keyword interval and its a known issue. (Or it's how the ANSI/ISO spec says it should work, bottom of page 205/top of page 206)
Here is a qoute from the oracle community blog:
Question:
select to_date('2012-feb-29','yyyy-mon-dd') + interval '1' year as dt from dual;
ORA-01839: date not valid for month specified
01839. 00000 - "date not valid for month specified"
*Cause:
*Action:
select to_date('2012-feb-29','yyyy-mon-dd') + interval '2' year as dt from dual;
ORA-01839: date not valid for month specified
01839. 00000 - "date not valid for month specified"
*Cause:
*Action:
select to_date('2012-feb-29','yyyy-mon-dd') + interval '3' year as dt from dual;
ORA-01839: date not valid for month specified
01839. 00000 - "date not valid for month specified"
*Cause:
*Action:
select to_date('2012-feb-29','yyyy-mon-dd') + interval '4' year as dt from dual;
29-FEB-16 00:00:00
select to_date('2012-feb-29','yyyy-mon-dd') + interval '1' day as dt from dual;
01-MAR-12 00:00:00
select to_date('2012-feb-29','yyyy-mon-dd') + interval '1' month as dt from dual;
29-MAR-12 00:00:00
Answer:
That's just how INTERVALs work. Leap years are the least of the
problem; adding 1 month to March 31 results in the same error. If you
want to make sure that the result is a valid DATE, then use
ADD_MONTHS. (There's no separate function for adding years; use
ADD_MONTH (SYSDATE, 12*n) to get the DATE that is n years from now.)
Why it happens in our case:
In our case, we used virtual private database for some of our tables because of security reasons. And there we applied the interval keyword in most of the selects.
What to do instead:
Use ADD_MONTHS instead.
select add_months(to_date('2012-feb-29','yyyy-mon-dd'), 12) as dt from dual;

How to handle to_date exceptions in a SELECT statment to ignore those rows?

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;

SSRS - Oracle DB, Passing Date parameter

Using SSRS with an Oracle Database. I need to prompt the user when running the report to enter a date for report. What is the best way to add in the parameter in my SSRS Report. Having problem finding the right date format. under the "Report Parameter" menu, I have setup the Report Parameters using the DateTime Datatype.
Keep getting this error "ORA-01843: Not a Valid Month"
Thank you for your help.
Select
a.OPR_Name,
a.OPR,
a.Trans_Desc,
a.Trans_Start_Date,
Cast(a.S_Date as date) as S_Date,
Sum(a.Duration) as T
From (
Select
US_F.OPR_Name,
ITH_F.OPR,
ITH_F.ITH_RID,
ITH_F.TRANSACT,
Transact.DESC_1 as Trans_Desc,
To_CHAR(ITH_F.Start_Time,'DD-Mon-YY') as Trans_Start_Date,
To_CHAR(ITH_F.Start_Time,'MM/DD/YYYY') as S_Date,
Substr(To_CHAR(ITH_F.Start_Time,'HH24:MI'),1,6) as Start_Time,
To_CHAR(ITH_F.End_Time,'DD-Mon-YY') as Trans_End_Date,
Substr(To_CHAR(ITH_F.End_Time,'HH24:MI'),1,6) as End_Time,
Cast(Case When To_CHAR(ITH_F.Start_Time,'DD-Mon-YY') = To_CHAR(ITH_F.End_Time,'DD-Mon-YY')
Then (((To_CHAR(ITH_F.End_Time,'SSSSS') - To_CHAR(ITH_F.Start_Time,'SSSSS')) / 60))/60
Else ((86399 - (To_CHAR(ITH_F.Start_Time,'SSSSS')) + To_CHAR(ITH_F.End_Time,'SSSSS'))/60)/60
End as Decimal(3,1)) as Duration
from Elite_76_W1.ITH_F
Left Join Elite_76_W1.Transact
on Transact.Transact = ITH_F.Transact
Left Join Elite_76_W1.US_F
on US_F.OPR = ITH_F.OPR
Where ITH_F.TRANSACT not in ('ASN','QC','LGOT')
) a
Where a.S_Date = #Event_Date
Having Sum(a.Duration) <> 0
Group By a.OPR_Name,
a.OPR,
a.Trans_Desc,
a.Trans_Start_Date,
a.S_Date
Order by a.OPR_Name
Oracle parameters are indicated with a leading colon - #Event_Date should be :Event_Date.
You use CAST(a.S_Date AS DATE) in your query, where a.S_Date is a VARCHAR: To_CHAR(ITH_F.Start_Time, 'MM/DD/YYYY'). If your session date parameter NLS_DATE_FORMAT is different from 'MM/DD/YYYY', this will result in a format error (in your case I suspect your NLS_DATE_FORMAT is something like DD-MON-YYYY, resulting in a "month" error).
A few options:
don't use TO_CHAR in the inner query (always try to keep the date format for internal calculations, use TO_CHAR only where it belongs -- in the GUI). If you only want the date portion, use TRUNC.
use TO_DATE instead of CAST in the outer query: to_date(a.S_Date, 'MM/DD/YYYY'), this is obviously tedious: you cast a date to a varchar that is later transformed to a date.

Resources