Building a table of numbers within a FOR LOOP - oracle

I have below procedure which I need to call from another procedure.
PROCEDURE get_list_ntds_for_given_port(
pis_olt_name IN common.types.string
, pis_chasis_lt_port IN common.types.string
, pona_ntd_ids OUT common_api.ntabtype
)
IS
lsa_object_name common_api.vtabtype;
lsa_link_type common_api.vtabtype;
lsa_link_status common_api.vtabtype;
lna_link_object_id common_api.ntabtype;
lsa_link_object_name common_api.vtabtype;
lsa_link_object_class common_api.vtabtype;
ln_pon_port_id NUMBER;
lna_child_pon_result FLS_NUMBER_TABLE;
lona_ntd_ids common_api.ntabtype;
ls_pon_port_map common.types.string;
BEGIN
ls_pon_port_map := pis_olt_name || '/' || pis_chasis_lt_port;
ln_pon_port_id := nwmdl.alu_pon_port.find(
pis_full_pon_port_name => ls_pon_port_map
);
lna_child_pon_result:= rm.sri_object_utils.get_child_objects(
pis_proc_name => lc_proc_name
, pin_parent_id => ln_pon_port_id
);
pona_ntd_ids := common_api.ntabtype();
FOR i IN 1..lna_child_pon_result.COUNT
LOOP
rm.ims_objects_api.get_peer_links (
pin_object_id => lna_child_pon_result(i)
, pis_geographical_only => 'N'
, pona_object_id => lona_ntd_ids
, posa_object_name => lsa_object_name
, posa_link_type => lsa_link_type
, posa_link_status => lsa_link_status
, pona_link_object_id => lna_link_object_id
, posa_link_object_name => lsa_link_object_name
, posa_link_object_class => lsa_link_object_class
);
pona_ntd_ids.EXTEND(lona_ntd_ids.COUNT);
FOR i IN 1..lona_ntd_ids.COUNT
LOOP
pona_ntd_ids(i) := lona_ntd_ids(i);
END LOOP;
END LOOP;
END get_list_ntds_for_given_port;
I simulate the external call with this pl-sql block:
SET SERVEROUTPUT ON;
DECLARE
lona_ntd_ids common_api.ntabtype;
BEGIN
svcmgr_lni.design_and_assign.get_list_ntds_for_given_port( pis_olt_name => 'SWOLT0000003DV'
,pis_chasis_lt_port => '1-1/LT1/1'
,pona_ntd_ids => lona_ntd_ids
);
FOR i IN 1..lona_ntd_ids.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE(lona_ntd_ids(i));
END LOOP;
END;
The problem is that I don't get any result in the output.
My guess is that my rm.ims_objects_api.get_peer_links API will be called for every lna_child_pon_result(i) found by rm.sri_object_utils.get_child_objectsand will put in the OUT param of the API more exactly in every output parm a table of numbers(ids) or varchar.
What I want to achive is to build the table of numbers of the main PROCEDURE(get_list_ntds_for_given_port) and set it to the output parameter so to use that table of numbers outside the main procedure.
Please leave any ideas that you have on solving this.

Try this:
Move "pona_ntd_ids := common_api.ntabtype();" outside the loops:
pona_ntd_ids := common_api.ntabtype();
FOR i IN 1..lna_child_pon_result.COUNT
Change
pona_ntd_ids(i) := lona_ntd_ids(i);
to
pona_ntd_ids(pona_ntd_ids.COUNT+1) := lona_ntd_ids(i);
Since in your original code you initialize pona_ntd_ids for every loop you will end up with nothing if the last outer iteration yields lona_ntd_ids.COUNT=0.

Lilte modification you can do and bulk collect the whole object and then make it as OUT param. Yes this will be a overhead on program as Regex is used but it will suffice your query.
FOR i IN 1..lona_ntd_ids.COUNT
LOOP
lv_eg_string := lona_ntd_ids(i)||','||lv_eg_string;
-- pona_ntd_ids(i) := lona_ntd_ids(i);
END LOOP;
lv_eg_string:=substr(lv_eg_string,1,length(lv_eg_string)-1);
SELECT regexp_substr(lv_eg_string,'[^,]+', 1, level) BULK COLLECT
INTO pona_ntd_ids
FROM dual
CONNECT BY regexp_substr(lv_eg_string, '[^,]+', 1, level);

Related

how to sort by different attribute each time we click a button pl/sql?

When I click the button for the first time, my selected column is sorted. When I click for the second time, it will sort in reverse.How can I do this?
Note: My program consists of dummy block. No data blocks
declare
cursor c is
select *
from muhasebe.doviz_takip
where UPPER(fatura_no) LIKE
NVL('%' || UPPER(:giris.sorgulama) || '%', UPPER(fatura_no))
order by fatura_no asc;
begin
go_block('XDOVIZ_TAKIP');
clear_block;
first_record;
for r in c loop
:FATURA_NO := r.fatura_no;
:ACIKLAMA := r.aciklama;
:YUKLEME_TAR := r.yukleme_tar;
:VARIS_TAR := r.varis_tar;
:TUTAR := r.tutar;
next_record;
end loop;
first_record;
end;
This is the code I can sort once
One option is to create a global variable (or a parameter), two cursors (one for each sorting) and IF-THEN-ELSE which decides which cursor to use, depending on global variable's value.
Something like this:
DECLARE
CURSOR c_asc IS
SELECT *
FROM muhasebe.doviz_takip
WHERE UPPER (fatura_no) LIKE
NVL ('%' || UPPER ( :giris.sorgulama) || '%',
UPPER (fatura_no))
ORDER BY fatura_no ASC;
CURSOR c_desc IS
SELECT *
FROM muhasebe.doviz_takip
WHERE UPPER (fatura_no) LIKE
NVL ('%' || UPPER ( :giris.sorgulama) || '%',
UPPER (fatura_no))
ORDER BY fatura_no DESC;
BEGIN
GO_BLOCK ('XDOVIZ_TAKIP');
CLEAR_BLOCK;
FIRST_RECORD;
:global.sort := NVL ( :global.sort, 'ASC');
IF :global.sort = 'DESC'
THEN
FOR r IN c_asc
LOOP
:FATURA_NO := r.fatura_no;
:ACIKLAMA := r.aciklama;
:YUKLEME_TAR := r.yukleme_tar;
:VARIS_TAR := r.varis_tar;
:TUTAR := r.tutar;
NEXT_RECORD;
END LOOP;
:global.sort := 'ASC';
ELSIF :global.sort = 'ASC'
THEN
FOR r IN c_desc
LOOP
:FATURA_NO := r.fatura_no;
:ACIKLAMA := r.aciklama;
:YUKLEME_TAR := r.yukleme_tar;
:VARIS_TAR := r.varis_tar;
:TUTAR := r.tutar;
NEXT_RECORD;
END LOOP;
:global.sort := 'DESC';
END IF;
FIRST_RECORD;
END;
Perhaps you could try to make it "smarter" (as this is pretty much dummy - repeating more or less the same code twice), but - this is simple and easy to maintain.
One another approach would be converting it to a database block by creating a view named v_doviz_takip such as
CREATE OR REPLACE VIEW v_doviz_takip AS
SELECT *
FROM muhasebe.doviz_takip
and setting the Query Data Source Name of the block xdoviz_takip to this
and adding a WHERE clause
UPPER(fatura_no) LIKE NVL('%' || UPPER(:giris.sorgulama) || '%', UPPER(fatura_no))`
to the block. Then add a line
SET_BLOCK_PROPERTY('xdoviz_takip',order_by, 'fatura_no');
to the WHEN-NEW-FORM-INSTANCE trigger.
And convert your current code block to this one :
DECLARE
v_ord VARCHAR2(25) := GET_BLOCK_PROPERTY('XDOVIZ_TAKIP',order_by);
BEGIN
GO_BLOCK ('XDOVIZ_TAKIP');
CLEAR_BLOCK;
IF v_ord = 'fatura_no' THEN v_ord := v_ord||' DESC'; ELSE v_ord := 'fatura_no' END IF;
SET_BLOCK_PROPERTY('XDOVIZ_TAKIP',order_by, v_ord);
EXECUTE_QUERY;
FIRST_RECORD;
END;
this way, it will sort descendingly by fatura_no for the first, and ascendingly for the second attempts
, or just converting the current IF clause to IF v_ord != 'fatura_no' ... would reversely change the behaviour.

What does '[^~]+' do?

I am reviewing some code that was written before I got to my company and I see this '[^~]+' used in a lot of code. To add some context it is a part of a for loop function.
DECLARE
new_parent_id number;
BEGIN
FOR i IN (
select regexp_substr(:PAGE1_SELECTED, '[^~]+', 1, level) material_num, rownum
from dual
connect by regexp_substr(:PAGE1_SELECTED, '[^~]+', 1, level) is not NULL)
LOOP
if i.ROWNUM = 1 then
new_parent_id := ASSIGN_NEW_MATERIAL (
pMATERIAL_NUMBER => i.MATERIAL_NUMBER,
pASSEMBLY_NAME => :PAGE1_NEW_ASSEMBLY
);
else
ASSIGN_MATERIAL_TO_PARENT (
pNEW_PARENT_ID => new_parent_id,
pPART_NUMBER => i.PART_NUMBER
);
end if;
END LOOP;
END;
I'd expect that :PAGE1_SELECTED is a tilde-separated string of material_num values that this code is parsing. If you're looking at the values of the bind variables when this code is called to determine that there are no tildes, I'd go back to the application to see if there are different code paths that could produce lists of values.

Item Query From Table and Send It To Procedure

Note
I want to query page item name and send the corresponding items value into a procedure. I can get the item name but couldn't get the value of it. At first I use the following code:
begin
for j in (select item_name from UTLITMINF where service_id ='abc' ) loop
val := val || ':' || j.item_name; --items name
END LOOP;
/* exe := ' begin
dynamic_api_call(p_service => :ser,
p_par => :v_val, --items value to need to send
o_result_json => :v_l_response_text);
end; ';
execute immediate exe
using IN ser,
in val,
out l_response_text;*/
begin
dynamic_api_call(p_service => 'abc',
p_par => val, --items name from page queried from table and send its value to procedure
o_result_json => l_response_text);
end;
raise_application_error(-20001,l_response_text);
end;
In val parameter it contains P11_CUSTOMER. But the value of it did not pass through the procedure. How can I get the value of it? Suggest me if i need to improve my code.
You can use the V (short for value) and NV (short for numeric value) function for dynamic item names. Try something like this (you'll need to adjust on your end).
declare
l_response_text varchar2(255);
l_ser varchar2(255) := 'abc';
l_item_name varchar2(255);
begin
select item_name
into l_item_name
from UTLITMINF
where service_id = l_ser;
dynamic_api_call(
p_service => l_ser,
p_par => v(l_item_name),
o_result_json => l_response_text
);
end;
Try the dynamic sql like the below
begin
for j in (select item_name from UTLITMINF where service_id ='abc' ) loop
val := val || ':' || j.item_name; --items name
END LOOP;
exe := ' begin
dynamic_api_call(p_service => :ser,
p_par => :v_val, --items value to need to send
o_result_json => :v_l_response_text);
end ;';
execute immediate exe
using ser,
val,
OUT l_response_text;
raise_application_error(-20001,l_response_text);

Not getting the desired results

enter code hereI have a Problem. Below pl/sql used to be working before and now i dont know whats happening... I want to insert records into a table called incoming from an interactive report using a check box
my sql is
SELECT apex_item.checkbox2(1,filenumber)
|| apex_item.hidden(2,filename)
|| APEX_ITEM.hidden(3,'&APP_USER. ')
|| APEX_ITEM.hidden(4,volume)
|| APEX_ITEM.hidden(6,filename)
as "SELECT",
FILENUMBER,
FILENAME,
LOCATION,
OPENDATE,
CLOSEDDATE,
VOLUME,
SUB,
temporary,
registryid,
STATUS
from REGISTRY
my pl/sql is
begin
for idx in 1 .. apex_application.g_f01.count
loop
if apex_application.g_f01(idx) is not null then
insert into incoming
(filenumber,
filename
)
values
(apex_application.g_f01(idx),
apex_application.g_f02(idx)
);
end if;
end loop;
end;
and all this happens after process..this was working fine.. However from recent the problem i am having is the pl/sql gives me the correct filenumber but the incorrect filename.
e.g
lets say the ir report has
filenumber filename
1 aaron
2 kerron
3 Joshua
when i select number 2 (second record) the result in the incoming table will be
filenumber filename
2 aaron
its always selecting the first record once it falls in the apex_item.hidden.
if i reverse it and put
SELECT apex_item.checkbox2(1,filename)
|| apex_item.hidden(2,filenumber)
the filename is correct and the file number will do what i explained above which is if i choose the second record i will get
filenumber filename
1 kerron
when i add
begin
for idx in 1 .. apex_application.g_f01.count loop
for i in 1..apex_application.g_f02.count loop
if apex_application.g_f01(idx) is not null then
insert into INCOMINGREQUESTNOTIFICATION
(requestedfile,filenumber
)
values
(apex_application.g_f01(idx),
apex_application.g_f02(i)
);
end if;
end loop;
end loop;
end;
#romeuBraga i am getting all 3 rows not the selected one can you tell me what am doing wrong
You need a hidden item to store the ID.
*1 and 2 store the same information
select column1,
column2,
column3,
apex_item.hidden(p_idx => 1,
p_value => code) ||
apex_item.checkbox2(p_idx => 2,
p_value => code) CheckBox,
other items
from x
in this case, you need this pl/sql to get the correct row values.
begin
for i in 1..apex_application.g_f01.count loop
for j in 1..apex_application.g_f02.count loop
if apex_application.g_f01(i) = apex_application.g_f02(j) then
--insert something here
end if;
end loop;
end loop;
end;

How do I call a function from within a PL/SQL process within Oracle APEX 4.2

I've created a new function called GET_FILENAME inside my Oracle APEX database. I'd like to call this function from within a APEX PL/SQL code block and pass it the filename. Below is the function I created in my APEX DB with SQL Dev.
create or replace function get_filename
(p_path IN VARCHAR2)
RETURN varchar2
IS
v_file VARCHAR2(100);
BEGIN
-- Parse string for UNIX system
IF INSTR(p_path,'/') > 0 THEN
v_file := SUBSTR(p_path,(INSTR(p_path,'/',-1,1)+1),length(p_path));
-- Parse string for Windows system
ELSIF INSTR(p_path,'\') > 0 THEN
v_file := SUBSTR(p_path,(INSTR(p_path,'\',-1,1)+1),length(p_path));
-- If no slashes were found, return the original string
ELSE
v_file := p_path;
END IF;
RETURN v_file;
END;
APEX side of things....
Below is the code I'd like to put in when calling the process.
TO_DATE(SUBSTR(GET_FILENAME(file_date),21,8),'YYYY-MM-DD')
Below is the apex process code and the comments are where I'd like to put it in.
BEGIN
APEX_COLLECTION.ADD_MEMBER
(
p_collection_name => 'PARSE_COL_HEAD',
p_c001 => 'C031',
p_c002 => 'FILE_DATE');
FOR UPLOAD_ROW IN (SELECT SEQ_ID FROM APEX_COLLECTIONS
WHERE COLLECTION_NAME = 'SPREADSHEET_CONTENT')
LOOP
APEX_COLLECTION.UPDATE_MEMBER_ATTRIBUTE (
p_collection_name => 'SPREADSHEET_CONTENT',
p_seq => UPLOAD_ROW.SEQ_ID,
p_attr_number => '31',
p_attr_value => :P25_FILE_NAME -- I want to call the process here
);
END LOOP;
END;
I don't normally answer my own question. But this was easier than I thought :). Below is the code I used to get this working....
BEGIN
APEX_COLLECTION.ADD_MEMBER
(
p_collection_name => 'PARSE_COL_HEAD',
p_c001 => 'C031',
p_c002 => 'FILE_DATE');
FOR UPLOAD_ROW IN (SELECT SEQ_ID FROM APEX_COLLECTIONS
WHERE COLLECTION_NAME = 'SPREADSHEET_CONTENT')
LOOP
APEX_COLLECTION.UPDATE_MEMBER_ATTRIBUTE (
p_collection_name => 'SPREADSHEET_CONTENT',
p_seq => UPLOAD_ROW.SEQ_ID,
p_attr_number => '31',
p_attr_value => TO_DATE(SUBSTR(GET_FILENAME(:P25_FILE_NAME),21,8),'YYYY-MM-DD')
);
END LOOP;
END;

Resources