ESQL transform from XML to COBOL and extarct date from string - ibm-integration-bus

I am ESQL newbie and transforming XML to Cobol copybook, one of the XML element is date but in string with a format yyyymmdd for example 20140908
I need to extract the year, month and day out of the string also in numeric
05 orderdate
10 orderyear PIC 9(4)
10 ordermonth PIC 9(2)
10 orderday PIC 9(2)
can I just say something like below:
DECLARE Orderdate INTEGER = CAST(INPUTROOT.XMLNS.ORDER.Order_Date as DateTime Format 'yyyymmdd');
SET OUTPUTROOT.DFDL.ORDERDATE.orderYear = EXTRACT(Year from Orderdate);
SET OUTPUTROOT.DFDL.ORDERDATE.orderMonth = EXTRACT(Month from Orderdate);
SET OUTPUTROOT.DFDL.ORDERDATE.orderDay = EXTRACT(Day from Orderdate);
Thanks Very much
J

Below works fine for me now but of course we can use substring for this and would have been a bit easier.
DECLARE ORDERDATE DATE;
DECLARE ORDERYEAR CHARACTER;
DECLARE ORDERMONTH CHARACTER;
DECLARE ORDERDAY CHARACTER;
SET ORDERDATE = CAST(InputRoot.XMLNSC.p:Order.p:Requested_Provision_Date AS DATE Format 'yyyymmdd');
SET ORDERYEAR = EXTRACT(YEAR FROM ORDERDATE);
SET ORDERMONTH = EXTRACT(MONTH FROM ORDERDATE);
SET ORDERDAY = EXTRACT(DAY FROM ORDERDATE);
SET OutputRoot.DFDL.ORDERS.ORDER_DATE.ORDER_YEAR = CAST(ORDERYEAR AS INTEGER);
SET OutputRoot.DFDL.ORDERS.ORDER_DATE.ORDER_MONTH = CAST(ORDERMONTH AS INTEGER);
SET OutputRoot.DFDL.ORDERS.ORDER_DATE.ORDER_DAY = CAST(ORDERDAY AS INTEGER);

Related

Oracle get all records between current day inserted with timestamp

Unable to retrieve records properly with the formatted date values, need select query with right date format to get all records inserted per day
I have a date string like this in my script -  
dateString :='26-MAR-20 05.00.00.00000000 AM';
I want to add 0.313 minutes to this date value. And also I want to
increment it to the next day something like this- '27-MAR-20
05.00.00.00000000 AM'; ​
I tried this 
dateString :='26-MAR-20 05.00.00.00000000 AM';
dateString :=to_char(dateField,'DD-MON-YYYY HH24:MI:SS.FF');
dateField := to_timestamp(dateString, 'DD/MON/YYYY HH24:MI:SS.FF') + 0.313 * INTERVAL '1' MINUTE;
​
I can see the output and inserted these values into the DB but
unable to retrieve records properly with these formatted date values..
I suspect it might be to do with the timestamp fields
When I run this query -
select *from rptallexceptions where exceptiontime between '27-MAR-2020 04.00.00.000000000 AM' and '28-MAR-2020 03.59.00.000000000 AM' order by exceptiontime desc;
​
--- this one gives 3833 records but expected is 4600
it shows only the records on 27th march., records inserted with timestamp containing 28th march are not retrieved..
select *from rptallexceptions where exceptiontime between '28-MAR-2020 04.00.00.000000000 AM' and '29-MAR-2020 03.59.00.000000000 AM' order by exceptiontime desc;
--- this one returns '0' rows
Excerpt from the script:
cnt :=cnt +1;
dateString :=to_char(dateField,'DD-MON-YYYY HH24:MI:SS.FF');
-- add time difference for each exception.
dateField := to_timestamp(dateString, 'DD/MON/YYYY HH24:MI:SS.FF') + 0.313 * INTERVAL '1' MINUTE;
-- after n*4600 exceptions,update date to next date.
IF REMAINDER(cnt,exceptionsPerDay) = 0 THEN
dateField := to_timestamp(dateField + 1,'DD/MON/YYYY HH24:MI:SS.FF');
END IF;
The way I see it, your problem is that you're comparing timestamps to strings.
Sample table:
SQL> create table test as
2 select to_timestamp('27.03.2020 04:00:00:000000', 'dd.mm.yyyy hh24:mi:ss:ff6') datum, 'A' name from dual
3 union all
4 select to_timestamp('28.03.2020 15:23:00:000000', 'dd.mm.yyyy hh24:mi:ss:ff6') datum, 'A' name from dual;
Table created.
Query should use timestamp, not string:
SQL> select *
2 from test
3 where datum between to_timestamp('25.03.2020 12:00:00:000000am', 'dd.mm.yyyy hh:mi:ss:ff6am') --> timestamp
4 and to_timestamp('28.03.2020 12:00:00:000000am', 'dd.mm.yyyy hh:mi:ss:ff6am'); --> timestamp
DATUM N
--------------------------------------------------------------------------- -
27.03.20 04:00:00,000000000 A
SQL>
You were kind of "lucky" (though, one might call it bad luck as your query didn't fail, but it produced wrong results, according to number of rows being returned) for not getting an error as my database raises (due to different NLS settings):
SQL> select *
2 from test
3 where datum between '25.03.2020 12:00:00:000000am' --> string
4 and '28.03.2020 12:00:00:000000am'; --> string
where datum between '25.03.2020 12:00:00:000000am'
*
ERROR at line 3:
ORA-01830: date format picture ends before converting entire input string
SQL>
Strings are handled differently than dates (or timestamps), or numbers. Maybe you'll see the difference clearly in this example:
SQL> with test (col) as
2 (select '1' from dual union all
3 select '9' from dual union all
4 select '20' from dual
5 )
6 select *
7 from test
8 where col < '9';
CO
--
1
20
SQL>
20 < 9? Yes, if those are strings. The same might have happened to you. Try with proper datatype.
When you do:
dateString :=to_char(dateField,'DD-MON-YYYY HH24:MI:SS.FF');
you are converting whatever is the initial value of dateField to a string; but it looks like that has has not been set yet, so you end up with an empty string (which is the same as null). Your original value of dateString is never being used.
If you skip that and just do:
dateString :='26-MAR-20 05.00.00.00000000 AM';
dateField := to_timestamp(dateString, 'DD/MON/YYYY HH24:MI:SS.FF') + 0.313 * INTERVAL '1' MINUTE;
​then you are converting the 2-digit year 20 with a YYYY format element, which will turn it into year 0020, not 2020; but you also don't have AM in the format model, so it will get ORA-01830 anyway, and have HH24 instead of HH. I think your to_char() is attempting to 'correct' the string format, but that's not a great approach.
If you can't control the starting string format then the model has to match that:
dateString :='26-MAR-20 05.00.00.00000000 AM';
dateField := to_timestamp(dateString, 'DD-MON-RR HH:MI:SS.FF AM') + 0.313 * INTERVAL '1' MINUTE;
which gives dateField a value of 2020-03-26 05:00:18.780000.
Later on you do:
dateField := to_timestamp(dateField + 1,'DD/MON/YYYY HH24:MI:SS.FF');
which is also doing an implicit conversion of dateField + 1 - which is converted to a date, incidentally as timestamp + number is a date, not a timestamp - to a string; which will use your NLS_DATE_FORMAT. Presumably that is something like 'DD-MON-YYYY'.
So stepping through that:
dateField + 1 => date '2020-03-27 05:00:18' (losing fractional seconds)
implicit to_char(dateField + 1) => string '27-Mar-2020' (losing time)
to_timestamp(to_char(dateField + 1), '...') => timestamp '2020-03-27 00:00:00.000000' (with time at midnight).
So your between is, at best going to find records between 2020-03-26 05:00:18.780000 and 2020-03-27 00:00:00.0000000 - so it won't pick up any records later than midnight on the 27th.
Don't convert to and from strings when you don't need to; leave data in its native data type (timestamp in this case) and use direct manipulation with intervals.
Using between isn't ideal anyway, because it is inclusive; it would be better to end up with:
exceptiontime >= timestamp '2020-03-26 05:00:18.780000'
and exceptionTime < timestamp '2020-03-27 05:00:18.780000'

How to convert YY to YYYY ORACLE

How to convert YY to YYYY, example below, if I run example below I will receive for year '0007':
DECLARE
lv_promcode_txt VARCHAR(6) := 'A0807X';
lv_prommth_txt VARCHAR2(7);
lv_promyear_txt VARCHAR2(7);
BEGIN
lv_prommth_txt := SUBSTR(lv_promcode_txt, 2,2);
DBMS_OUTPUT.PUT_LINE('Month of promo code is: '||
TO_(TO_DATE(lv_prommth_TXT,'MM'), 'MONTH'));
lv_promyear_txt := SUBSTR(lv_promcode_txt, 4,2);
DBMS_OUTPUT.PUT_LINE('Year of promo code is: '||TO_CHAR(TO_DATE
(lv_promyear_txt, 'YYYY'),'YYYY'));
END;
Your format mask is wrong. Example:
select TO_CHAR(TO_DATE (SUBSTR('A0807X', 4,2), 'YY'),'YYYY') from dual
returns 2007
Replace your last DBMS_OUTPUT.PUT_LINE part of the code with
DBMS_OUTPUT.PUT_LINE('Year of promo code is ( Style 1 ) : '||TO_CHAR(TO_DATE(lv_promyear_txt, 'YYYY'),'YYYY'));
DBMS_OUTPUT.PUT_LINE('Year of promo code is ( Style 2 ) : '||TO_CHAR(TO_DATE(lv_promyear_txt, 'RRRR'),'YYYY'));
Just changing YYYY literal RRRR is enough in TO_DATE function.
This concept is related to year 2k problem.
For a date TO_DATE('18', 'RRRR') gives the result 2018 as year ( for
the current century, and the last two digits of years are between 00-49 ),
while
For a date TO_DATE('74', 'RRRR') gives the result 1974 as year ( for
the previous century, and the last two digits of years are between 50-99 )

Oracle PLSQL get difference between 2 datetime fields ignoring days

I would like to find the simplest way of calculating the difference in hours between 2 dates from Oracle datetime fields whilst ignoring the days, months & years portion. For example:
Datetime 1 (DATE variable) = 10/05/2017 16:00:00
Datetime 2 (DATE variable) = 15/05/2017 19:34:23
Required result (NUMBER output) = 3.576 hours
This is formula will be used in a PLSQL procedure, the output needs to be a number as above. I would imagine some combination of TO_DATE & TRUNC might work. Any help would be most appriciated and apologies if this is a duplicate question.
Use the sssss date mask to get just the time element as the number of seconds since midnight. Then it's just a matter of simple arithmentic:
select (to_number(to_char(datetime2, 'sssss'))
- to_number(to_char(datetime1, 'sssss')) / 3600 as diff_hours
from dual;
PL/SQL version is the same....
declare
Datetime1 DATE := to_date('10/05/2017 16:00:00', 'dd/mm/yyyy hh24:mi:ss');
Datetime2 DATE := to_date('15/05/2017 19:34:23', 'dd/mm/yyyy hh24:mi:ss');
hours_diff number;
begin
hours_diff := (to_number(to_char(datetime2, 'sssss'))
- to_number(to_char(datetime1, 'sssss'))) / 3600 ;
dbms_output.put_line(hours_diff);
end;

How to add stored procedure variables to SSRS 2012 Labels

Very new to SSRS so bear with me...
I created an SSRS report based on a stored procedure and as part of that procedure I calculate a StartDate and EndDate for my report. I need to use those two dates in the Title of the report but those variables are not part of the dataset created from the stored procedure.
How do I add those variables to the Title of the report?
Here is the code:
DECLARE #ThisDate date;
SET #ThisDate = getdate(); -- Current date
DECLARE #sdate AS int
SELECT #sdate = CONVERT(int, CONVERT(varchar(10), dateadd(yy, datediff(yy, 0, #ThisDate) - 2, 0), 112)) -- Beginning of previous 2 year
DECLARE #edate AS int
SELECT #edate = CONVERT(int, CONVERT(varchar(10), dateadd(mm, datediff(mm, -1, #ThisDate) - 1, -1), 112)) -- Last Day of previous month
Want my report to display:
From #sdate through #edate ( from 01-01-2014 through 08-31-2016 )
I appreciate the help!
The way you have it now, I would add a SELECT line to use in a dataset:
SELECT #sdate as START_DATE, #edate AS END_DATE
Your expression would have to use a LOOKUP to get the values from the dataset:
="From " & FIRST(Fields!START_DATE.Value, "DataSet1") & " through " & FIRST(Fields!END_DATE.Value, "DataSet1")
HOWEVER, the better way to do what you want is to use SSRS parameters to calculate your START_DATE and END_DATE and then use the parameters when you need the start and end dates.
START_DATE Parameter -
Date Type: DATE
Available Value Expression:
="01/01/" & (YEAR(TODAY) - 2)

SELECT * FROM T_TRANS WHERE TIME_START = to_date('01-09-2014', 'DD-MM-YY');

Sory, I have Question ? Why not show up when I execute some of its field content.
Please help me to fix it. Thank U
SELECT * FROM T_TRANS WHERE TIME_START = to_date('01-09-2014', 'DD-MM-YY');
Oracle is being a bit lenient with you with the date format mask, but you should use YYYY to make it clearer. But you're still providing a single point in time as midnight on that date:
select to_char(to_date('01-09-2014', 'DD-MM-YY'), 'YYYY-MM-DD HH24:MI:SS') as two_digit,
to_char(to_date('01-09-2014', 'DD-MM-YYYY'), 'YYYY-MM-DD HH24:MI:SS') as four_digit
from dual;
TWO_DIGIT FOUR_DIGIT
------------------- -------------------
2014-09-01 00:00:00 2014-09-01 00:00:00
Given the name of the column it's reasonable to assume you have other times, and your query won't match anything except exactly midnight. To find all records on that day, you need to provide a range:
SELECT * FROM T_TRANS
WHERE TIME_START >= to_date('01-09-2014', 'DD-MM-YYYY');
AND TIME_START < to_date('02-09-2014', 'DD-MM-YYYY');
... though I prefer the ANSI date notation for this sort of this:
WHERE TIME_START >= DATE '2014-09-01'
AND TIME_START < DATE '2014-09-02'
You could specify 23:59:59 on the same date, but that will break subtly when you use a timestamp field rather than a date field.
You could also truncate the value from the table (as #San said in a comment), or convert to a string for comparison (as #yammy showed in an answer), but either of those will prevent any index on the time_start column being used, affecting performance.
After reading Alex Poole suggestion, you should try:
SELECT * FROM T_TRANS WHERE to_char(TIME_START, 'DD-MM-YYYY') = '01-09-2014';
Shouldn't the format mask be "DD-MM-YYYY"?

Resources