SSRS 2005 passing datetime parameter to Oracle - oracle

I have a SSRS 2005 report runs on a Oracle 9 database.
The report use this simple query to return a dataset
SELECT order_number FROM apps.oe_order_headers_all
WHERE ordered_date >= to_date(:start_date,'DD-MON-YYYY')
AND ordered_date < to_date(:end_date,'DD-MON-YYYY') +1
The parameters work fine if they are of type string in SSRS. E.g. 01-JAN-2014 for both start_date and end_date. But if changed to datetime the report returns nothing (if in string, the report returns many rows). I really want to use the date picker control of SSRS.
This is probably more of a SSRS thing than Oracle thing?

This is probably a date conversion issue, but I'm surprised it isn't either erroring, or returning the same data - at least for the example date you gave.
In your previous question you were entering a string, so adding the to_date() made sense. But if you're binding it as a date then you do not want those.
This is fine:
to_date(<string>,'DD-MON-YYYY')
But this:
to_date(<date>,'DD-MON-YYYY')
is really doing:
to_date(to_char(<date>,<NLS_DATE_FORMAT>), 'DD-MON-YYYY')
If your `NLS_DATE_FORMAT happens to be the same as the fixed format you supplied, then this is kind of OK as it's just a redundant conversion to a string and back. But if they are different then you'll get errors or incorrect results.
For example, if my NLS_DATE_FORMAT is MM/DD/YYYY' thento_date(sysdate, 'DD-MON-YYYY) gets anORA-01843: not a valid montherror, because it's trying to interpret28as the month and02` as the day.
So you just need to simplify it to:
SELECT order_number FROM apps.oe_order_headers_all
WHERE ordered_date >= :start_date
AND ordered_date < :end_date +1
Given the odd error you get from this, you could also try:
AND ordered_date < :end_date + interval '1' day
... but without understanding why the simpler +1 is erroring I'm not confident that will help. It doesn't seem to be following the normal datetime arithmetic rules. This is another possibility but should not be necessary:
AND ordered_date < CAST(:end_date AS DATE) + 1

Related

Query not filtering with date in Oracle

There are records in table for particular date. But when I query with that value, I am unable to filter the records.
select * from TBL_IPCOLO_BILLING_MST
where LAST_UPDATED_DATE = '03-09-21';
The dates are in dd-mm-yy format.
To the answer by Valeriia Sharak, I would just add a few things since your question is tagged Oracle. I was going to add this as a comment to her answer, but it's too long.
First, it is bad practice to compare dates to strings. Your query, for example, would not even execute for me -- it would end with ORA-01843: not a valid month. That is because Oracle must do an implicit type conversion to convert your string "03-09-21" to a date and it uses the current NLS_DATE_FORMAT setting to do that (which in my system happens to be DD-MON-YYYY).
Second, as was pointed out, your comparison is probably not matching rows due LAST_UPDATED_DATE having hours, minutes, and seconds. But a more performant solution for that might be:
...
WHERE last_update_date >= TO_DATE('03-09-21','DD-MM-YY')
AND last_update_date < TO_DATE('04-09-21','DD-MM-YY')
This makes the comparison without wrapping last_update_date in a TRUNC() function. This could perform better in either of the following circumstances:
If there is an index on last_update_date that would be useful in your query
If the table with last_update_date is large and is being joined to other tables (because it makes it easier for Oracle to estimate the number of rows from your table that are inputs to the join).
Your column might contain hours and seconds, but they can be hidden.
So when you filter on the date, oracle implicitly adds time to the date. So basically you are filtering on '03-09-21 00:00:00'
Try to trunc your column:
select * from TBL_IPCOLO_BILLING_MST
where trunc(LAST_UPDATED_DATE) = '03-09-21';
Hope, I understood your question correctly.
Oracle docs

Computing date difference from within DevExpress

We use a third-party software that uses DevExpress for building reports. Normally on Oracle - I can get the difference in dates with ease by simply subtracting them:
TRUNC(sysdate) - TRUNC(a.birth_date) AS datediff
I used the same logic from within DevExpress:
CAST(CAST(CURRENT_DATE AS VARCHAR(9)) AS DATE) - CAST(CAST(a.birth_date AS VARCHAR(9)) AS DATE) AS datediff
But doing so gives me this error message:
Invalid cast from 'Decimal' to 'DateTime'. Couldn't store <35> in DATEDIFF Column.
Expected type is DateTime.
How do I fix this?
Notes:
There's a lot of casting going on here but that's just a work-around because TRUNC doesn't work so I'm basically just casting to a VARCHAR essentially removing the time portion and casting it back to a DATE field.
CURRENT_DATE is the equivalent of SYSDATE in the world of DevExpress.
Looks like the simplest solution is to cast the result to decimal.
CAST(CAST(CAST(CURRENT_DATE AS VARCHAR(9)) AS DATE) - CAST(CAST(a.birth_date AS VARCHAR(9)) AS DATE) AS DECIMAL) AS datediff

Validating Date Prompt To be less than Current Date OBIEE

I have a requirement to create two validations on the date prompt:
1) The From Date has to be less than To Date
2) The To Date has to be less than or equal to current date
I created a conditional analysis wherein From Date is < To Date, which works, but when I try to create an advanced filter wherein #To_Date <= Current_Date I am getting an error.
Error getting drill information: SELECT date'2016-08-24' saw_0 FROM "Workforce Management - Processed Time Cards Real Time" WHERE(date'#{To_Date}' <= (SELECT VALUEOF("CURRENT_DATE_REP_OTBI") FROM "Workforce Management - Processed Time Cards Real Time" FETCH FIRST 1 ROWS ONLY))
If anyone can help solve this, it'd be really helpful!
Thanks
You need to add a default value when referencing presentation variables in logical SQL queries or formulas. Especially if these are dates.
I created an analysis based on the following LogicalSQL and it worked.
SELECT date'2016-08-26' saw_0 from "subject_area" WHERE (date
#{to_date}{'2016-08-26'} < CURRENT_DATE)
Notice the following:
The presentation variable #{to_date} goes with a default value (noted by the second curly brackets). This helps OBIEE to validate the query. Failing to add the default value will give you the "getting drill information" error.
Instead of a session RPD variable, you can use CURRENT_DATE. It simplifies the query.
The above query will return the date in the SELECT clause, but if the to_date is greater than CURRENT_DATE will return no data.

Obtaining a list of date to control file import

I have a need to pull in via FTP only files from dates I haven't pulled data. The data pulls happen nightly, but occasionally there is an issue and a night gets skipped, and it will be picked up the following night.
I located a query on StackOverflow which addressed most of my problem. However, I'm left with an uncomfortable solution and a lingering question.
I have a table with data from each file downloaded. The crux of the data I'm using for this example is EXTRACT_DATE. The file format is filename_20160809.csv, as an example. Uses the 4-digit year, 2-digit month and 2-digit day to make unique. The FTP location has thousands of files, and I only want to grab the new, based on this date.
First, I get the latest EXTRACT_DATE from my table as such
SELECT MAX(EXTRACT_DATE) INTO checkDate FROM FILE_DETAILS;
I had attempted to do this in a single query, but couldn't work it, and finally attempted to create a variable, checkDate, and use this variable in a subsequent query to obtain my list. However, having two queries in a single script is not allowed, or I haven't found a way to do it. So my primary issue is to return the value of the latest date. Then call a new query or procedure with the value incorporated in to obtain my list, with this query
SELECT TO_DATE(checkDate, 'MM/DD/YYYY') + rownum AS EXTRACT_DATES
FROM ALL_OBJECTS
WHERE TO_DATE(checkDate, 'MM/DD/YYYY') + rownum <= TO_DATE(SYSDATE, 'DD-MM-YY');
This solution is messy and uncomfortable, I would prefer a single query to get back my results, rather then 2 scripts or a script and a procedure.
The lingering question, the result from the query returns dates in the mm/dd/yyyy format; 8/9/2016. I adjusted the TO_DATE to match.
Initially, it was set to return as YYYY-MM-DD; 2016-08-09.
However, it wouldn't return in this format. It would only come back as 8/9/2016, regardless of the TO_DATE formatting used. I don't understand why the date is coming back in this format.
SELECT TO_DATE('2-AUG-2016', 'DD-MON-RR') + rownum AS EXTRACT_DATES
FROM ALL_OBJECTS
WHERE TO_DATE('2-AUG-2016', 'DD-MON-RR') + rownum <= TO_DATE(SYSDATE, 'DD-MM-YY');
EXTRACT_DATES
8/3/2016
8/4/2016
8/5/2016
8/6/2016
8/7/2016
8/8/2016
8/9/2016
NLS_DATE_FORMAT is set to DD-MON-RR, with American as NLS_DATE_LANGUAGE.

Oracle a non-numeric character was found where a numeric was expected

I have problem with some thing input multiple date through prompt
my query something like
select something
from
something
where
to_date (bus.TDATE) not in (:didb1)
I want to input like '12-Jun-2016','11-Jun-2016'
i am doing php oracle,
My code following:
select bus.*,con.* from
BusinessPayment bus,
ConsumerPayment con
where bus.TDATE=con.TDATE
and to_date (bus.TDATE) not in (:didbv)
');
$bscode1='11-June-2016','10-June-2016','09-June-2016';
oci_bind_by_name($stid, ':didbv', $bscode1);
oci_execute($stid);
You can't use a single bind variable to represent a list of values in an in() clause. Bind variables don't contain multiple values; the value you bind is seen as a single string value. So you're effectively doing:
where
to_date (bus.TDATE) not in (q'['11-June-2016','10-June-2016','09-June-2016']')
If TDATE is already a date type - which it hopefully is, and the joins suggest it might be - then you should not be passing that through to_date() - you are doing an implicit conversion from date to string, then a semi-explicit conversion back to a date, both using your session's NLS_DATE_FORMAT. That is either doing unnecessary work, or losing resolution, depending on your format model and whether the dates have times. If the intention is to ignore the time part of the value then there are better ways to do that.
Anyway, since that is a date now whatever type it was before, the right had side of that filter will also be converted to a date, so you're doing:
where
to_date (bus.TDATE) not in (to_date(q'['11-June-2016','10-June-2016','09-June-2016']'))
... and it's that which is throwing the exception, whatever your NLS settings are. Even if you passed a single value it would error because of the embedded single quotes. You can replicate that with:
select to_date(q'['11-June-2016','10-June-2016','09-June-2016']') from dual;
which also gets ORA-01858: a non-numeric character was found where a numeric was expected.
Ideally you would pass the individual date strings as elements of an array, but you can also work around this with an XML hack. You can pass a single string containing comma-delimited values to XMLTable(), and it will split it in to rows:
select * from xmltable(q'['11-June-2016','10-June-2016','09-June-2016']');
COLUMN_VALUE
--------------------------------------------------------------------------------
11-June-2016
10-June-2016
09-June-2016
Then you can convert each of those values to a date:
select to_date(column_value, 'DD-Month-YYYY')
from xmltable(q'['11-June-2016','10-June-2016','09-June-2016']')
and use that in a subquery or a join:
select * from dual
where trunc(sysdate) not in (select to_date(column_value, 'DD-Month-YYYY')
from xmltable(q'['11-June-2016','10-June-2016','09-June-2016']'));
And that works with a string bind variable, so your code would be:
select bus.*,con.*
from BusinessPayment bus
join ConsumerPayment con
on bus.TDATE=con.TDATE
where bus.TDATE not in (select to_date(column_value, 'DD-Month-YYYY')
from xmltable(:didbv));
I've modified this to use ANSI join syntax, which isn't relevant but there's rarely a reason to use the ancient syntax you have. If TDATE does include the time you'll need to modify it a bit - truncating is simplest but might affect performance.
Or you could join:
select bus.*,con.*
from xmltable(:didbv) x
join BusinessPayment bus
on bus.TDATE >= to_date(x.column_value, 'DD-Month-YYYY')
and bus.TDATE < to_date(x.column_value, 'DD-Month-YYYY') + 1
join ConsumerPayment con
on bus.TDATE=con.TDATE
In this version TDATE can have a time, and it matches any time on the days specified in the bind variable.
It would be better to supply the dates in a format that doesn't have the month name in it, as that could give you problems when run in different sessions or locales. If you know the PHP side will always be English you could force that to be recognised:
on bus.TDATE >= to_date(x.column_value, 'DD-Month-YYYY', #NLS_DATE_LANGUAGE=ENGLISH')
but if you can change the PHP format to use month numbers, and change the Oracle format model to match, that would be a bit simpler.

Resources