PLSQL variable doesn't get assigned by the given value - oracle

I am trying to assign a value from a table type variable to a varchar2 type table
CREATE OR REPLACE PACKAGE BODY TEST_SYS IS
TYPE line_table IS TABLE OF VARCHAR2(32767) INDEX BY BINARY_INTEGER;
PROCEDURE test(
val_ OUT VARCHAR2)
IS
temp_val VARCHAR2(4000);
svalues_ line_Table;
BEGIN
svalues_(1) := '! -$FILE_LINE=EXT01;2017-01;2017-
12;JJ01;;4021;;;;;;;;;;;;USD;;;;;;;;1000;1000;; -';
temp_val := svalues_(1);
val_ := temp_val;
END test;
END TEST_SYS
value assignment seems does not happen in the following statement. Does anybody has a clue on this?
temp_val := svalues_(1);
This example only for problem replicate, It may be not logically enhanced one. only to understand the problem.

Provided you have a package test_sys with code :
CREATE OR REPLACE PACKAGE TEST_SYS IS
PROCEDURE test( val_ OUT VARCHAR2);
END TEST_SYS;
and body of the package :
CREATE OR REPLACE PACKAGE BODY TEST_SYS IS
TYPE line_table IS TABLE OF VARCHAR2(32767) INDEX BY BINARY_INTEGER;
PROCEDURE test( val_ OUT VARCHAR2) IS
temp_val varchar2(4000);
svalues_ line_Table;
BEGIN
svalues_(1) := '! -$FILE_LINE=EXT01;2017-01;2017-12;JJ01;;4021;;;;;;;;;;;;USD;;;;;;;;1000;1000;; -';
temp_val := svalues_(1);
val_ := temp_val;
dbms_output.put_line(val_);
END test;
END TEST_SYS;
and call procedure test, you will be able to get the results as in the following :
SQL> set serveroutput on;
SQL> var str varchar2(4000);
SQL> exec test_sys.test(:str);
PL/SQL procedure successfully completed
str
---------
! -$FILE_LINE=EXT01;2017-01;2017-12;JJ01;;4021;;;;;;;;;;;;USD;;;;;;;;1000;1000;; -

Related

Call procedure with nested table as parameter

How code procedure with nested table parameter? In table test I need insert data from loop eg. 1,2,3...
plsql
Declare
TYPE code_nt is table of varchar2(10);
l_codes code_nt := code_nt();
begin ​
​FOR i IN 1..APEX_APPLICATION.G_F01.COUNT LOOP
l_codes.extend;
l_codes(i) := to_char(i);
​END LOOP;
//here call procedure
//PKG_EMP.INSERT_EMP(PAR_1);
end;
package:
create or replace PACKAGE PKG_EMP AS
TYPE code_nt is table of varchar2(10);
l_codes code_nt := code_nt();
procedure INSERT_EMP (PAR_1 code_nt);
END;
create or replace PACKAGE BODY PKG_EMP AS
procedure INSERT_EMP (PAR_1 code_nt) AS
BEGIN
INSERT INTO test (ID) VALUES (value from code_nt);
END;
end;
Your code will not work as code_nt is a locally defined type in both your PL/SQL function and the PL/SQL anonymous block and despite having the same name and signature they are different data types.
You need to use the same data type in both:
Declare
l_codes PKG_EMP.code_nt := PKG_EMP.code_nt();
begin ​
FOR i IN 1..APEX_APPLICATION.G_F01.COUNT LOOP
l_codes.extend;
l_codes(i) := to_char(i);
-- or
-- l_codes(i) := TO_CHAR( APEX_APPLICATION.G_F01(i) );
​END LOOP;
PKG_EMP.INSERT_EMP(l_codes);
END;
/
You can declare your package as:
CREATE PACKAGE PKG_EMP AS
TYPE code_nt is table of varchar2(10);
PROCEDURE INSERT_EMP (PAR_1 code_nt);
END;
/
CREATE PACKAGE BODY PKG_EMP AS
procedure INSERT_EMP (PAR_1 code_nt) AS
BEGIN
FORALL i IN 1 .. par_1.COUNT
INSERT INTO test (ID) VALUES ( par_1(i) );
END;
END;
/
db<>fiddle here

assigning a oracle PLSQL variable with URL

I have a task in which i need to create a rest API call within a stored procedure in Oracle.
I have looked at the following documentation as an example.
https://technology.amis.nl/2015/05/11/invoke-a-rest-service-from-plsql-make-an-http-post-request-using-utl_http-in-oracle-database-11g-xe/
in my PLSQL i am trying to set my url variable to the following string:
https://localhost/access_token?client_id=1234&client_secret=1234&grant_type=client_credentials
using the following
v_url := 'https://localhost/access_token?client_id=1234'||chr(38) ||'client_secret=1234'||chr(38) ||'grant_type=client_credentials';
However the variable is not being set as it is coming back null. The variable can be set up to the point before the '&'
create or replace procedure mule_test( p_clientid in varchar2,
p_clientsecret in varchar2)
AS
req utl_http.req;
res utl_http.resp;
v_url VARCHAR2(255); v_name VARCHAR2(255);
v_buffer varchar2(4000);
v_content varchar2(4000);
begin
v_url := 'https://localhost/access_token?client_id=1234'||chr(38)
||'client_secret=1234'||chr(38) ||'grant_type=client_credentials';
Works OK for me:
SQL> set serveroutput on
SQL> declare
2 v_url varchar2(200);
3 begin
4 v_url := 'https://localhost/access_token?client_id=1234'||chr(38) ||'client_secret=1234'||chr(38) ||'grant_type=client_credentials';
5 dbms_output.put_line(v_url);
6 end;
7 /
https://localhost/access_token?client_id=1234&client_secret=1234&grant_type=client_credentials
PL/SQL procedure successfully completed.
SQL>

Using collection inside dynamic sql

I am trying to pass dbms_sql.number_table from one procedure to another and then using it inside a dynamic plsql block. But the below code throws error as:
Error(6,17): PLS-00306: wrong number or types of arguments in call to '||'
create or replace
procedure proc1( v_in_table_name varchar2,
v_in_column_name varchar2,
v_in dbms_sql.number_table)
as
plsql_block varchar2(4000);
begin
plsql_block:='declare
begin
FORALL INDX IN 1 ..'||v_in.count||' SAVE EXCEPTIONS
UPDATE '||v_in_table_name||'
Set '||v_in_column_name||'=123 WHERE col2='||v_in||'(INDX)||;
end';
execute immediate plsql_block;
end proc1;
You should make two changes:
First(and its case of error) its when you concatinate string with collection.
If you want to send collection into pl/sql block you shoud use the param.
And second you should add ; in the end of dynamic pl\sql:
create or replace
procedure proc1(v_in dbms_sql.number_table)
as
plsql_block varchar2(4000);
begin
plsql_block:='declare
l_collect dbms_sql.number_table := :number_table ;
begin
FORALL INDX IN 1 ..'||v_in.count||' SAVE EXCEPTIONS
UPDATE table_name
Set col1=123 WHERE col2=l_collect(INDX);
end;';
execute immediate plsql_block using v_in;
end proc1;
But after all changes I would like to ask: Are you realy need to use dynamic pl\sql?
There is no need for using a dynamic block. Also i dont think it can work as well. You can use this way;
create or replace
procedure proc1(v_in dbms_sql.number_table)
as
plsql_block varchar2(4000);
l_collect dbms_sql.number_table;
begin
l_collect := v_in;
FORALL INDX IN 1 ..l_collect.count SAVE EXCEPTIONS
UPDATE table_name
Set col1=123
WHERE col2=l_collect(INDX);
commit;
end proc1;
Execution:
SQL> DECLARE
var DBMS_SQL.number_table;
BEGIN
var (1) := 1;
var (2) := 2;
var (3) := 3;
proc1 (var);
END;
/
PL/SQL procedure successfully completed.
EDIT: As per your edit the code becomes like:
create or replace procedure proc1 (v_in_table_name varchar2,
v_in_column_name varchar2,
v_in dbms_sql.number_table)
as
plsql_block varchar2 (4000);
begin
plsql_block := q'[ FORALL INDX IN 1 ..v_in.count SAVE EXCEPTIONS
UPDATE :table_name
Set :col1=123
WHERE col2=v_in(INDX)]';
execute immediate plsql_block using v_in_table_name, v_in_column_name;
commit;
end proc1;

Procedure to update a table which is already populated

I want to create a procedure that adds new rows to an already existing table.But with the current procedure I've, I'm rewriting the entire table. The code for the current procedure is
CREATE TYPE t_tf_row AS OBJECT (
id NUMBER,
description VARCHAR2(50));
CREATE TYPE t_tf_tab IS TABLE OF t_tf_row;
create or replace procedure add_n_rows(
n_rows in number)
is
l_tab t_tf_tab := t_tf_tab();
begin
for i in l_tab.count .. l_tab.count + n_rows
loop
l_tab.extend;
l_tab(l_tab.last) := t_tf_row(i, 'Description for '|| i);
end loop;
end;
Here, everytime I'm rewriting the entire l_tab. I want to update the one which is already updated. Suggest me the right method for the required procedure.Thanks
This is because you're re-creating the object. You need to pass an instantiated version of the object into the procedure as a parameter:
create or replace procedure add_n_rows(
Pn_rows in number
, P_tab in out t_tf_tab ) is
begin
for i in P_tab.count .. P_tab.count + Pn_rows
loop
P_tab.extend;
P_tab(l_tab.last) := t_tf_row(i, 'Description for '|| i);
end loop;
end;
I've declared P_tab as an OUT parameter, this means you can alter it. If you don't want to do this then remove "out" and declare a local variable of the type t_tf_tab, which you can then alter.
You can then call it separately, for instance:
declare
l_tab t_tf_tab := t_tf_tab();
begin
l_tab.extend;
l_tab(l_tab.last) := t_tf_row(1. 'Hello');
add_n_rows(3, l_tab);
end;

Procedure to input number and output varchar2

I need to write a procedure to input let's say a rep_id and then output the rep_name that corresponds to the rep_id.
After that, I need to use another procedure to call the above procedure.
Here is what I have for the first procedure.
create or replace procedure p_inout
(v_rep_id in number)
As
v_first_name varchar2(20);
v_last_name varchar2(20);
begin
select first_name,last_name into v_first_name, v_last_name
from rep
where rep_id = v_rep_id;
dbms_output.put_line(v_first_name||' '||v_last_name);
end p_inout;
/
Execute p_inout(100);
And here is my procedure to call the above procedure
create or replace procedure p_call
is
v_first_name varchar2(20);
v_last_name varchar2(20);
begin
p_inout(100);
dbms_output.put_line(v_first_name||' '||v_last_name);
end p_call;
/
execute p_call
I was able to get the result but one guy told me that my call procedure should be like this
Create or replace procedure p_call
Is
V_name varchar2(20);
Begin
P_inout(100,v_name); --100 is a rep id
Dbms_output.Put_line(v_name);
End;
/
Execute p_call
Doesn't my procedure to call and his call procedure produce the same result?
CREATE TABLE minions (
rep_id DATE CONSTRAINT minions__rep_id__pk PRIMARY KEY,
rep_name NUMBER CONSTRAINT minions__rep_name__nn NOT NULL
CONSTRAINT minions__rep_name__u UNIQUE
)
/
CREATE OR REPLACE PROCEDURE myCatWasSick (
p_rep_id IN minions.rep_id%TYPE,
p_rep_name OUT minions.rep_name%TYPE
)
IS
BEGIN
SELECT rep_name
INTO p_rep_name
FROM minions
WHERE rep_id = p_rep_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
p_rep_name := NULL;
END myCatWasSick;
/
CREATE OR REPLACE PROCEDURE releaseTheBadgers
IS
the_badger NUMBER(10);
BEGIN
myCatWasSick( SYSDATE + 1, the_badger );
// Do something with the_badger.
END releaseTheBadgers;
/

Resources