Extract values from nested object in plsql using Apex - plsql

I have this employee object and I need to store every value into variables.
I am wondering if it is an easy or smart way to get the values from nested objects.
I know I can get the values in this way:
v_first_name := APEX_JSON.get_varchar2(p_path => 'employee.firstName')
but how can I retrieve the values from address object or from options object?
Apex version 20.1.
{
"employee":{
"firstName":"John",
"lastName":"Smith",
"email":"jsmith#test.com",
"phoneNumber":"‎(907) 247-8888",
"address":{
"street":"1527 Pond Reef Rd",
"city":"Ketchikan",
"state":"ALaska",
"stateShort":"AK",
"zipCode":99901,
"country":"USA"
},
"categories":[
{
"categoryID":1,
"categoryName":"Example1",
"options":{
"ind_1":1,
"ind_2":0,
"ind_3":0
}
},
{
"categoryID":2,
"categoryName":"Example",
"options":{
"ind_1":1,
"ind_2":1,
"ind_3":1
}
}
]
}
}

address is just a nested json object so you can use the "dot" notation. categories is an array so you need to loop through the individual elements. Here is an example.
SET SERVEROUTPUT ON
DECLARE
l_json_text VARCHAR2(32767);
l_count PLS_INTEGER;
l_members WWV_FLOW_T_VARCHAR2;
l_paths APEX_T_VARCHAR2;
l_exists BOOLEAN;
l_json_values apex_json.t_values;
BEGIN
l_json_text := '
{
"employee":{
"firstName":"John",
"lastName":"Smith",
"email":"jsmith#test.com",
"phoneNumber":"‎(907) 247-8888",
"address":{
"street":"1527 Pond Reef Rd",
"city":"Ketchikan",
"state":"ALaska",
"stateShort":"AK",
"zipCode":99901,
"country":"USA"
},
"categories":[
{
"categoryID":1,
"categoryName":"Example1",
"options":{
"ind_1":1,
"ind_2":0,
"ind_3":0
}
},
{
"categoryID":2,
"categoryName":"Example",
"options":{
"ind_1":1,
"ind_2":1,
"ind_3":1
}
}
]
}
}
';
apex_json.parse(
p_values => l_json_values,
p_source => l_json_text
);
DBMS_OUTPUT.put_line('----------------------------------------');
if apex_json.does_exist(p_path => 'employee.address.street',p_values => l_json_values) then
dbms_output.put_line('address: '||apex_json.get_varchar2(p_path => 'employee.address.street', p_values => l_json_values));
end if;
DBMS_OUTPUT.put_line('----------------------------------------');
DBMS_OUTPUT.put_line('----------------------------------------');
if apex_json.does_exist(p_path => 'employee.categories',p_values => l_json_values) then
dbms_output.put_line(APEX_JSON.get_count(p_path => 'employee.categories', p_values => l_json_values) || ' Categories found');
FOR r IN 1 .. APEX_JSON.get_count(p_path => 'employee.categories', p_values => l_json_values) LOOP
DBMS_OUTPUT.put_line('categoryName: '||apex_json.get_varchar2(p_path => 'employee.categories[%d].categoryName', p0 => r, p_values => l_json_values));
DBMS_OUTPUT.put_line('options.ind_1: '||apex_json.get_varchar2(p_path => 'employee.categories[%d].options.ind_1', p0 => r, p_values => l_json_values));
END LOOP;
end if;
DBMS_OUTPUT.put_line('----------------------------------------');
END;
/
----------------------------------------
address: 1527 Pond Reef Rd
----------------------------------------
----------------------------------------
2 Categories found
categoryName: Example1
options.ind_1: 1
categoryName: Example
options.ind_1: 1
----------------------------------------
PL/SQL procedure successfully completed.

Related

How can I get PL/JSON array of array value

How can I retrieve content from below JSON using Pl/JSON?
i need to fetch values of first array and second array
{
"documents1": [
{
"key": "NATID",
"validations": [
{
"error": "Field is required"
}
]
}
]
}
for example i have written the query as below which returns values of first array without any issue, but it doesn't return values of array of an array
DECLARE
obj json
:= json
('{
"documents1": [
{
"key": "NATID",
"validations": [
{
"error": "Field is required"
}
]
}
]
}'
);
list_value json_list;
list_value_validation json_list;
LIST_VALUES json_list;
BEGIN
list_value := json_list (obj.get ('documents'));
FOR i IN 1 .. list_value.COUNT
LOOP
DBMS_OUTPUT.put_line ( 'key->'
|| json_ext.get_string (json (list_value.get (i)),
'key'
)
);
----------below scripts are not working
list_value_validation := json_list (list_value.get ('values'));
FOR iv IN 1 .. list_value_validation.COUNT
LOOP
DBMS_OUTPUT.put_line
( 'error->'
|| json_ext.get_string
(json (list_value_validation.get (iv)
),
'error'
)
);
END LOOP;
END LOOP;
END;
modified the code as below and it's working fine.
BEGIN
list_value := json_list (obj.get ('documents'));
FOR i IN 1 .. list_value.COUNT
LOOP
p_string_docs := list_value.get (i).TO_CHAR ();
obj_docs := json (p_string_docs);
l_output := json_ext.get_string (obj_docs, 'key');
list_docs_validation := json_list (obj_docs.get ('values'));
FOR i IN 1 .. list_docs_validation.COUNT
LOOP
l_output :=
json_ext.get_string (obj_docs, 'key')|| ' | '
|| json_ext.get_string (json (list_docs_validation.get (i)),
'code'
);
DBMS_OUTPUT.put_line (l_output);
END LOOP;
END LOOP;
END;

Doctrine: return one dimensional

I have a ManyToOne relation between two entities ArticleLine and Artcile:
<?php
//ArticleLine.php
ManyToOne(targetEntity="Gain\Bundle\ArticleBundle\Entity\Article")
I'm trying to get the list of Ids based on some where conditions..
This my doctrine query dql:
SELECT tl.id FROM AppBundle\Entity\ArticleLine tl INNER JOIN tl.turnover t INNER JOIN tl.article a WHERE t.supplier = :supplier AND t.year = :year AND tl.significant = false ORDER BY tl.id asc
After calling $qb->getQuery()->getResult() I'm getting this result of arrays...
array:138 [
0 => array:1 [
"id" => 64624
]
1 => array:1 [
"id" => 64630
]
2 => array:1 [
"id" => 64631
]
3 => array:1 [
"id" => 64632
]
4 => array:1 [
"id" => 64633
]
5 => array:1 [
"id" => 64637
]
6 => array:1 [
"id" => 64638
Any idea how I can transform my result to a one dimensional array or playing on hydration mode to get something like this
[64624, 64630, 64631, 64633 ... ]
or
[0 => 64624, 1 => 64630, 2 => 64631 ...]
You can transform your result with an array_map function:
$result = $qb->getQuery()->getResult()
$result = array_map('current', $result);
You can also use array_column fucntion:
$result = array_column($result, "id")
If a solution exists with an hydration mode. I would like to know :)

Loop through reference cursor insert into API and catch exceptions

I am not sure why I am encountering an exception error. I am still learning PL/SQL. I am trying to put some data into a cursor from a table. Then loop through the cursor and insert the data into an API and catch the records that are rejected by the API's. Can I do one loop for multiple API's? Is there something else that I am missing?
declare
fhw UTL_FILE.FILE_TYPE;
wdir varchar2(100);
wfilename varchar2(100);
cnt number;
aidy number;
--
TYPE NextGen_rec IS RECORD(
r_pidm rprawrd.rprawrd_pidm%TYPE,
r_aidy_code rprawrd.rprawrd_aidy_code%TYPE,
r_term_code rpratrm.rpratrm_term_code%TYPE,
r_fund_code rprawrd.rprawrd_fund_code%TYPE,
r_awst_code rprawrd.rprawrd_awst_code%TYPE,
r_awst_date rprawrd.rprawrd_awst_date%TYPE,
r_accept_amt rprawrd.rprawrd_accept_amt%TYPE,
r_accept_date rprawrd.rprawrd_accept_date%TYPE,
r_offer_amt rprawrd.rprawrd_offer_amt%TYPE,
r_offer_date rprawrd.rprawrd_offer_date%TYPE,
r_data_origin rprawrd.rprawrd_data_origin%TYPE
);
--
--
TYPE cur1 IS REF CURSOR;
ng cur1;
--
Begin
--
Wdir := 'UTL_TTU_ST';
wfilename := 'ng_errors.csv';
fhw := UTL_FILE.FOPEN(wdir,wfilename,'w');
select count (*) into cnt
from ttubanr.NGAWARDLD, ttubantemp.NGAWARD
where NGAWARD_AIDY = NGAWARDLD_AIDY;
--
if cnt = 0 then
select NGAWARD_AIDY into aidy from ttubantemp.NGAWARD
where ROWNUM < 2;
--insert aid year if it doesn't exist with date from 01-01-2000 as place holder.
insert into ttubanr.NGAWARDLD
(NGAWARDLD_AIDY, NGAWARDLD_LD)
SELECT replace(replace (REPLACE (NGAWARD_AIDY, 'Academic Year ',null),'20',null),'-',null), '01-JAN-2017' FROM ttubantemp.NGAWARD;
end if;
-- Last date for aid year found
--
for award_rec in ng_rec loop
If cnt = 1 then
open ng FOR
SELECT NGAWARD_NGID,
replace(replace (REPLACE (NGAWARD_AIDY, 'Academic Year ',null),'20',null),'-',null)NGAWARD_AIDY,
CASE
WHEN NGAWARD_PERIOD = 'FALL'
THEN SUBSTR(NGAWARD_AIDY,15,4)||80
WHEN NGAWARD_PERIOD = 'SPRING'
THEN SUBSTR(NGAWARD_AIDY,20,4)||10
END NGAWARD_TERM,
(SELECT SPRIDEN_PIDM FROM SPRIDEN WHERE SPRIDEN_ID = NGAWARD_ID AND SPRIDEN_CHANGE_IND IS NULL) NGAWARD_PIDM,
NGAWARD_ID,
NGAWARD_FUND,
NGAWARD_AMT,
CASE WHEN NGAWARD_PERIOD = 'ANNUAL'
THEN 'A'
WHEN NGAWARD_PERIOD = 'FALL'
THEN 'F'
WHEN NGAWARD_PERIOD = 'SPRING'
THEN 'S'
END NGAWARD_PERIOD,
CASE WHEN NGAWARD_STATUS = 'GrantAward'
THEN 'I'
WHEN NGAWARD_STATUS = 'ModifyAward'
THEN 'U'
WHEN NGAWARD_STATUS = 'RemoveSingleSeasonAward'
THEN 'C'
WHEN NGAWARD_STATUS = 'RevokeRenewableAward'
THEN 'C'
WHEN NGAWARD_STATUS = 'DeleteAward'
THEN 'C'
END NGAWARD_STATUS,
NGAWARD_ADATE
FROM ttubantemp.NGAWARD, ttubanr.NGAWARDLD, SPRIDEN
WHERE
SPRIDEN_ID = NGAWARD_ID
AND NGAWARD_AIDY = NGAWARDLD_AIDY
and NGAWARD_ADATE > NGAWARDLD_LDATE
AND SPRIDEN_CHANGE_IND IS NULL
order by NGAWARD_ID, NGAWARD_FUND, NGAWARD_ADATE;
fetch ng into ng_rec;
End If;
--
IF ng_rec.NGAWARD_PERIOD = 'A' AND ng_rec.NGAWARD_STATUS = 'I'
THEN
rp_award.p_create(p_aidy_code => ng_rec.NGAWARD_AIDY,
p_pidm => ng_rec.NGAWARD_PIDM,
p_fund_code => ng_rec.NGAWARD_FUND,
p_awst_code => 'A',
p_awst_date => sysdate,
p_accept_amt => ng_rec.NGAWARD_AMT,
p_accept_date => sysdate,
p_offer_amt => ng_rec.NGAWARD_AMT,
p_offer_date => sysdate,
p_data_origin => 'NextGen');
--
gb_common.p_commit;
--Year award Update
ELSIF ng_rec.NGAWARD_PERIOD = 'A' AND ng_rec.NGAWARD_STATUS = 'U'
THEN
rp_award.p_update(p_aidy_code => ng_rec.NGAWARD_AIDY,
p_pidm => ng_rec.NGAWARD_PIDM,
p_fund_code => ng_rec.NGAWARD_FUND,
p_awst_code => 'A',
p_awst_date => sysdate,
p_accept_amt => ng_rec.NGAWARD_AMT,
p_accept_date => sysdate,
p_offer_amt => ng_rec.NGAWARD_AMT,
p_data_origin => 'NextGen');
--
gb_common.p_commit;
--Year award cancel
ELSIF ng_rec.NGAWARD_PERIOD = 'A' AND ng_rec.NGAWARD_STATUS = 'C'
THEN
rp_award.p_update(p_aidy_code => ng_rec.NGAWARD_AIDY,
p_pidm => ng_rec.NGAWARD_PIDM,
p_fund_code => ng_rec.NGAWARD_FUND,
p_awst_code => 'C',
p_awst_date => sysdate,
p_data_origin => 'NextGen');
--
gb_common.p_commit;
--Term award insert
ELSIF ng_rec.NGAWARD_PERIOD in ('F','S') AND ng_rec.NGAWARD_STATUS = 'I'
THEN
rp_award_schedule.p_create(p_aidy_code => ng_rec.NGAWARD_AIDY,
p_term_code => ng_rec.NGAWARD_TERM,
p_pidm => ng_rec.NGAWARD_PIDM,
p_fund_code => ng_rec.NGAWARD_FUND,
p_awst_code => 'A',
p_awst_date => sysdate,
p_accept_amt => ng_rec.NGAWARD_AMT,
p_accept_date => sysdate,
p_offer_amt => ng_rec.NGAWARD_AMT,
p_offer_date => sysdate,
p_data_origin => 'NextGen');
--
gb_common.p_commit;
--Term award update
ELSIF ng_rec.NGAWARD_PERIOD in ('F','S') AND ng_rec.NGAWARD_STATUS = 'U'
THEN
rp_award_schedule.p_update(p_aidy_code => ng_rec.NGAWARD_AIDY,
p_term_code => ng_rec.NGAWARD_TERM,
p_pidm => ng_rec.NGAWARD_PIDM,
p_fund_code => ng_rec.NGAWARD_FUND,
p_accept_amt => ng_rec.NGAWARD_AMT,
p_offer_amt => ng_rec.NGAWARD_AMT,
p_data_origin => 'NextGen');
--
gb_common.p_commit;
EXCEPTION
WHEN OTHERS THEN
gb_common.p_rollback;
IF SQLCODE = gb_event.APP_ERROR THEN
utl_file.put_line(fhw,'Rollback renumbering '||sqlerrm||','||ng_rec.NGAWARD_NGID||','||ng_rec.NGAWARD_ID||','||ng_rec.NGAWARD_AIDY||','||ng_rec.NGAWARD_TERM||','||ng_rec.NGAWARD_FUND||','||ng_rec.NGAWARD_AMT||','||ng_rec.NGAWARD_STATUS||','||ng_rec.NGAWARD_ADATE);
--
end loop;
--
end if;
--
--CLOSE ng_rec;
UTL_FILE.FCLOSE(fhw);
end;

Linq divided by zero error?

How can check following code to catch divided by zero error?
active = (g.Sum(x => x.Kullanim_Reaktif) / g.Sum(x => x.kullanim_T0)) * 100
I want something like this:
if(g.Sum(x => x.kullanim_T0) == 0)
{
return 1;
}
else
{
return g.Sum(x => x.kullanim_T0);
}
Can I write if-else in above linq code line (g.Sum(x => x.kullanim_T0))? And how?
Thanks.
active = (g.Sum(x => x.kullanim_T0) == 0 ? 1 : g.Sum(x => x.Kullanim_Reaktif) / g.Sum(x => x.kullanim_T0)) * 100
but more efficient to do:
var kSum = g.Sum(x => x.kullanim_T0);
active = (kSum == 0 ? 1 : g.Sum(x => x.Kullanim_Reaktif) / kSum ) * 100

Getting start and end date of a PHP DatePeriod object?

How can i get the start and end date of a DatePeriod object?
$today = new \DateTime(date('Y-m-d')); // 2012-05-30
$period = new \DatePeriod($today, new \DateInterval('P1M'), 1);
$stats = new UsageStatistics($period);
class UsageStatistics
{
protected $period, $sentEmailCount, $autoSentEmailCount;
public function __construct(\DatePeriod $period)
{
$this->period = $period;
// Current logged in user and email repository
$user = $this->getUser();
$repo = $this->getEmailRepository();
// Get the start and end date for the given period
$startDate = ...
$endDate = ...
$result = $repo->getAllSentCount($user, $startDate, $endDate);
// Assigning object properties
}
public function getSentEmailCount() { return $this->sentEmailCount; }
public function getAutoSentEmailCount() { return $this->autoSentEmailCount; }
}
DatePeriod only implements the Traversable interface and has no other methods to either access elements or retrieve them.
You can do something easy to get start/end dates:
$periodArray = iterator_to_array($period);
$startDate = reset($periodArray);
$endDate = end($periodArray);
I'm using PHP 5.6.9 and it seems that you can use the properties end and start to access your beginning and end DateTime objects:
$p = new DatePeriod($s, $i, $e);
$startTime = $p->start; //returns $s
$endTime = $p->end; //returns $e
The PHP documentation doesn't seem to reflect this. I did a print_r of a DatePeriod object and got the following output:
DatePeriod Object
(
[start] => DateTime Object
(
[date] => 2015-06-01 00:00:00.000000
[timezone_type] => 3
[timezone] => America/Los_Angeles
)
[current] => DateTime Object
(
[date] => 2015-06-08 00:00:00.000000
[timezone_type] => 3
[timezone] => America/Los_Angeles
)
[end] => DateTime Object
(
[date] => 2015-06-08 00:00:00.000000
[timezone_type] => 3
[timezone] => America/Los_Angeles
)
[interval] => DateInterval Object
(
[y] => 0
[m] => 0
[d] => 7
[h] => 0
[i] => 0
[s] => 0
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] =>
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
[recurrences] => 1
[include_start_date] => 1
)
It seems that properties current and interval are also visible.
The solution posted by #hakre and #Boby is not correct.
The $endDate is end of the period when PERIOD % INTERVAL = 0.
All other cases $endDate will be END - PERIOD.
$startingDate = new DateTime($startingDay);
$startingDate->modify('previous day');
$startingDate->modify('next Sunday');
$endingDate = new DateTime($endingDay);
$endingDate->modify('next day');
$period = new DatePeriod($startingDate, new DateInterval('P1W'), $endingDate);

Resources