Is it possible to call procedure inside a view in snowflake? - stored-procedures

i have below table and stored procedure.
D | state | temp
-------------------------------
2021-06-21 |New York |69
2021-06-22 |Texes |70
#stored procedure
create or replace procedure get_state_based_on_temp(temp_value integer)
returns table(state string)
language sql
as
$$
declare
res resultset default (select state from temp_table1 where temp <= :temp_value);
begin
return table(res);
end;
$$;
i am trying to create a view below
create or replace view tem_result_view as select doc.d as date_in, view_temp.state from temp_table1 doc, table(get_state_based_on_temp(69)) as view_temp;
But it reurns below error
Unknown table function GET_STATE_BASED_ON_TEMP
i am able to call the function as
call get_state_based_on_temp(70);
which return the result.
Any solution to this issue?

A procedure can not be called inside a view. UDFs / functions can be called inside a view.
Have you tried to use a SQL table function (UDTF)?
create or replace function get_state_based_on_temp(temp_value integer)
returns table (state varchar)
as
$$
select state from temp_table1 where temp <= temp_value
$$;
https://docs.snowflake.com/en/sql-reference/functions-table.html

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

Unable to execute snowflake master procedure (calls another procedure) from ADF lookup

I have a stored procedure in Snowflake which calls two other stored procedures. This is getting executed in Snowflake and working successfully. I want to call this using ADF. I have already tried calling other stored procedure in ADF pipeline and they work using lookup activity.
However, it is not working for this particular master procedure. I think ADF is not able to go to the child procedures.
Sample snowflake query:
CREATE OR REPLACE PROCEDURE CHILD1(DBNAME VARCHAR)
RETURNS VARCHAR(16777216)
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
var result="";
var sql_command = `Truncate table if exists ${DBNAME}.PUBLIC.EMPLOYEE`;
snowflake.execute ({sqlText: sql_command});
return result;
$$
;
CREATE OR REPLACE PROCEDURE MASTER(DBNAME VARCHAR)
RETURNS VARCHAR(16777216)
LANGUAGE JAVASCRIPT
EXECUTE AS CALLER
AS
$$
var result="";
var sql_command = `CALL CHILD1(?)`;
snowflake.execute ({sqlText: sql_command, binds: [DBNAME]});
return result;
$$
;
ADF design:
Lookup query:
#concat('CALL PUBLIC.EMPLOYEE(',pipeline().parameters.DB_NAME,')')
Passing the database name as parameter

Call one stored procedure to another stored procedure in DB2

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;

Delphi Postgres stored procedure

I am working on Delphi application which deals with stored procedures.I created stored procedure for insert statement and it works fine for my application.
Now,I wanted to create the same for select statement.
CREATE TYPE list_all_firstname AS ( first_name character varying);
CREATE FUNCTION select_sp()
RETURNS SETOF list_all_firstname AS
$$
DECLARE
rec record;
BEGIN
FOR rec IN (SELECT first_name FROM person) LOOP
RETURN NEXT rec;
END LOOP;
END;
$$ LANGUAGE plpgsql;
The call is:
SELECT * FROM select_sp();
Till this everything is fine in postgres.I wanted to access this stored procedure in my delphi application.
My code is:
with StoredProc2 do begin
StoredProcName :='select_sp';
ExecProc;
Edit5.Text:=ParamByName('list_all_firstname').AsString ;
end;
But i gets the error saying "Could not find object".How do i access return values of stored procedure in delphi??
I got the answer..could not find object is BDE error...
Next thing is accessing values,no need to use stored procedure component.We can use TQuery as below...:
Query1.SQL.Clear;
Query1.SQL.Add('SELECT * FROM select_sp()');
Query1.Active := True;
for i:=0 to Query1.RowsAffected-1 do
begin
sval:=Query1.FieldByName('first_name').AsString;
ShowMessage(sval);
Query1.Next;
end;

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