Call one stored procedure to another stored procedure in DB2 - stored-procedures

Problem that I was facing is that I have to call one stored procedure from another stored procedure in DB2 database. Kind example that I am giving right below.
I have one stored procedure:
CREATE OR REPLACE PROCEDURE Proc1()
IS
Declare myName in varchar;
BEGIN
Select fname into myName from student where fname='x'; // is returning unique value
-- here call anoher proc2
END;
Now so this proc1 procedure is going to call this proc2 procedure.
Now I have second stored procedure:
CREATE OR REPLACE PROCEDURE Proc2(Name in varchar)
IS
BEGIN
-- do anything
END;

I solved this problem,
So solution is like If we want to execute proc using sql command then syntex is like below,
call Proc2('My Name');
We can use this same approach inside our proc also.
For that we have to follow some steps. Lets say that our above sql call is statement that we want to execute. we are going to convert that statement into String and pass necessary parameter by concating variable values. Then execute statement.
CREATE OR REPLACE PROCEDURE Proc1()
IS
Declare myName in varchar;
-- stmt variable is to execute our proc
STMT VARCHAR(4000);
BEGIN
Select fname into myName from student where fname='x'; // is returning unique value
-- this is our logic
STMT :='call Proc2('||myName||')';
EXECUTE IMMEDIATE STMT;
END;

Related

Assigning default value to snowflake stored procedure arguments

Is it possible to have default values in arguments of Stored procedures of Snowflake. For the below example, I am getting error. Please help
syntax error line 1 at position 53 unexpected ''test''.
create or replace procedure test(arg1 string default 'test')
returns string not null
language sql
as
$$
begin
return arg1;
end;
$$
;
Snowflake's procedures applies polymorphism instead of using default value. This solution is when you do not want to call sp like func1(Null)
For example (sql scripting):
create or replace procedure func1(arg1 varchar, arg2 varchar)
...
create or replace procedure func1(arg1 varchar)
...
call func1(arg1 , 'some-default-value')
...
One option could be providing NULL as value and handle it at the begining of the stored procedure with COALSESCE:
create or replace procedure test(arg1 string)
returns string not null
language sql
as
$$
begin
arg1 := COALESCE(arg1, 'test');
return arg1;
end;
$$;
CALL test(NULL);
-- test
Setting a default value/values as arguments directly in Stored procedures is not available in Snowflake currently
The below link can be referred for the allowed syntax in Stored Procedures
https://docs.snowflake.com/en/sql-reference/sql/create-procedure.html#syntax

How to get the restult table of a stored procedure into a temp table?

Enviroment:
DB2 Version 11.1,
OS - Linux
How to get the result table of stored procedure into a temp table?
The table and the result have the same table configuration (firstColumn int, secondColumn nvarchar(255))
I'm assuming your stored procedure returns an open cursor, so you want to consume that cursor, inserting its contents into a session table (declared global temporary table) on Db2-LUW.
In addition to fetch and insert statements, you need to understand the following statements:
associate result set locator ... with procedure ...
allocate ... cursor for result set ...
Here is a deliberately artificial example of a nested stored procedure, which shows fetching a result-set from a nested procedure into a session table. The purpose is to show how the syntax works, rather than to do anything useful with data (as the net effect can be equally met by a simple catalog query in this case). This example can be run at the Db2 command-line (for example at the bash shell, after you connected to a database with appropriate permissions):
update command options using s on ;
--#SET TERMINATOR #
create or replace procedure alltabs
dynamic result sets 1
language sql
specific alltabs
begin
declare v_cur cursor with return to caller for select tabschema,tabname,type from syscat.tables ;
open v_cur;
end#
declare global temporary table session.thetables(tabschema varchar(128), tabname varchar(128))
not logged with replace on commit preserve rows #
create or replace procedure populate_dgtt()
language sql
specific populate_dgtt
begin
declare v_rs result_set_locator varying;
declare v_tabschema varchar(128);
declare v_tabname varchar(128);
declare v_type char(1);
declare sqlstate char(5) default '00000';
call alltabs;
associate result set locator (v_rs) with procedure alltabs;
allocate v_rscur cursor for result set v_rs;
fetch from v_rscur into v_tabschema, v_tabname, v_type;
while ( sqlstate = '00000') do
if v_type='V' and v_tabschema='SYSSTAT'
then
insert into session.thetables(tabschema,tabname) values (v_tabschema, v_tabname);
end if;
fetch from v_rscur into v_tabschema, v_tabname, v_type;
end while;
return;
end#
call populate_dgtt()#
select rtrim(Tabschema)||'.'||rtrim(tabname) from session.thetables #

Accept user input and set assign to variable PL/SQL

I am trying to accept user input inside of a stored procedure and assign it to a VARCHAR variable. For some reason I get error
PLS-00201: identifier 'userinput' must be declared.
Any ideas? I have to use this later down the line to see how many times the input appears in a table.
CREATE OR REPLACE PROCEDURE nums
AS
x_num VARCHAR(20);
BEGIN
x_num := &input;
dbms_output.put_line('You entered: ' || x_num);
END;
/
Procedures cannot receive user input in response to a prompt, PLSQL is NOT interactive. When you have that you are not actually communicating with the database. What is actually happening is symbol substitution were SQLPLUS or other interface (Toad , SQL Developer, ...) is actually intercepting symbol, requesting the input, and physically changing the script before submitting it to the database. If you want a stored procedure you will need to use a parameter as #HereGoes suggested and then provide the user a script as follows:
Begin
nums(pInput => &Input);
end ;
Or provide an application interface to receive the input value and call the procedure or allow user access through SQLPLUS or other interface and let them enter the script - not recommended.
I suggest making the input a parameter.
CREATE OR REPLACE PROCEDURE nums (pInput IN VARCHAR2)
AS
x_num VARCHAR(20);
BEGIN
x_num := pInput ;
dbms_output.put_line('You entered: ' || x_num);
END;
/

How to define an Array of values (or a Column) into a Procedure Argument?

I am working on a Netezza SP and is stuck with a problem.
I have a SP, defined as say:
CREATE OR REPLACE PROCEDURE MY_PROC(VARCHAR(ANY)) RETURNS INTEGER LANGUAGE NZPLSQL
AS
BEGIN_PROC
DECLARE
v_temp ALIAS FOR $1;
/* Other decalarations */
result_ts INTEGER;
BEGIN
result_ts := 0;
/* Procedure Body */
RETURN result_ts;
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE 'Exception Raised: %', SQLERRM;
END;
END_PROC;
If I am running this SP with one value, such as:
SELECT MY_PROC('TEST_INPUT');
But if I am trying to run it with a column value, such as:
SELECT MY_PROC(TEST_COLUMN) FROM TEST_TABLE;
Its giving me error as:
ERROR: Can't use a stored procedure in this context
I know that in the second scenario I am passing an Array (i guess) but this is not what the Procedure has expected.
Now I am trying to have a procedure that can accept these kind of values but could not succeeded so far, LOOPing and all I have taken care but only problem is the Argument which I don't know how to pass.
Any help would be appreciated, let me know if I need to provide any extra info on this.
Asif
Stored procedures in Netezza, as of v7.2, can only be called in the following ways, as documented here.
CALL sproc_name(...);
EXEC sproc_name(...);
SELECT sproc_name(...);
Note that the SELECT form does not allow a FROM clause.
If you want the stored procedure to act on a particular column from a particular table that changes from invocation to invocation, you could pass the names of those as arguments to the stored procedure and have the entirety of the SQL logic encoded within. You could even pass arbitrary code into the stored procedure to build a query internally.
The way you are trying to call it now is more like calling a user defined function, and that simply won't work with stored procedures here.

Get specific fields from sys_refcursor in stored proc?

I am running an Oracle 9i server at my office. I am working on a procedure that passes a sys_refcursor as an out parameter to another package (along with other in parameters). I was able to define a type as a record of the various columns that the called procedure returns in the cursor. I can then loop over with code like this:
LOOP
fetch o_results into v_rec;
exit when o_results%notfound;
dbms_output.put_line(v_rec.some_id);
end loop;
Is there a way to only pull one column and not have to declare an entire rowtype? I tried something like:
LOOP
fetch o_results.some_id into v_id;
exit when o_results%notfound;
dbms_output.put_line(v_id);
end loop;
But that didn't work. Any other ideas?
No, you cannot fetch a single column into a local variable other than a record if the cursor returns a result set with multiple columns. However, you do have a few alternatives.
If you declare a strongly-typed cursor rather than a weakly typed cursor, you could declare your local variable based on that cursor definition rather than declaring a new collection.
create or replace procedure cursor_proc
as
cursor emp_cur
is
select empno, ename
from emp;
l_row emp_cur%rowtype;
begin
open emp_cur;
loop
fetch emp_cur into l_row;
exit when emp_cur%notfound;
dbms_output.put_line( l_row.ename );
end loop;
close emp_cur;
end;
Alternately, if you know that the weakly typed ref cursor will always return all the columns in a particular object, you can anchor your local variable declaration to that object. You can always make this work by declaring a view that your cursor selects from. For example
create or replace view vw_emp
as
select ename, empno
from emp
create or replace procedure cursor_proc2
as
emp_cur sys_refcursor;
l_row vw_emp%rowtype;
begin
open emp_cur for select * from vw_emp;
loop
fetch emp_cur into l_row;
exit when emp_cur%notfound;
dbms_output.put_line( l_row.ename );
end loop;
close emp_cur;
end;
Finally, if you use an implicit cursor, Oracle will implicitly declare the collection type
create or replace procedure cursor_proc3
as
begin
for emp in (select ename, empno from emp)
loop
dbms_output.put_line( emp.ename );
end loop;
end;

Resources