Snowflake sql stored procedure bind variable not set - snowflake-cloud-data-platform

I try to run in snowflake the following sql stored procedure with a declare variable inside but i got the following error : Error: Bind variable for object MYTABLE AS MYTABLE not set (line 13).
when I hard code the value into the function identifier it's work by the way...
CREATE OR REPLACE PROCEDURE DBNAME.SCHEMANAME."SP_test"()
RETURNS varchar
LANGUAGE SQL
EXECUTE AS CALLER
AS
declare
MYTABLE varchar := 'DBNAME.SCHEMANAME.TABLENAME';
--MYRESULT varchar;
BEGIN
-- let MYTABLE varchar := 'DBNAME.SCHEMANAME.TABLENAME';
-- MYTABLE := 'DBNAME.SCHEMANAME.TABLENAME';
--filter to return 1 row
-- let MYRESULT varchar := ( select col1 from IDENTIFIER( 'DBNAME.SCHEMANAME.TABLENAME' ) where col2=2 ) ;
--ko
let MYRESULT varchar := ( select col1 from IDENTIFIER( :MYTABLE ) where col2=2 ) ;
return :MYRESULT;
end;

This works for me:
CREATE OR REPLACE PROCEDURE "SP_test"()
RETURNS varchar
LANGUAGE SQL
EXECUTE AS CALLER
AS
$$
declare
MYRESULT resultset;
MYTABLE varchar := 'SERGIU_TESTDB.PUBLIC.CITIBIKE_TRIPS';
MYVAL varchar;
BEGIN
MYRESULT := (select ride_id from identifier(:MYTABLE) limit 1);
let c1 cursor for MYRESULT;
for row_variable in c1 do
MYVAL := row_variable.ride_id;
end for;
return MYVAL;
END
$$;
Calling it:
CALL "SP_test"();
I get a value out of it:
B1CE81D802D68DF8

Related

Snowflake Stored Procedure Error for JSON input

I am trying to parse JSON value and getting Syntax Error in stored procedure.
This SELECT statement works fine:
SELECT
parse_json ('{"fName":"Pink","lName":"Panther"}') AS json_data,
json_data:fName::string AS first_name,
json_data:lName::string AS last_name;
While trying same thing in stored procedure, I am getting a syntax error:
CREATE OR REPLACE PROCEDURE extract_json(input_json varchar)
RETURNS TABLE (res varchar)
LANGUAGE SQL
AS
$$
DECLARE
qry string;
res resultset;
BEGIN
qry := 'SELECT parse_json('||:input_json||') AS json_data::sting, json_data:fName::string';
res := (execute immediate qry);
return table(res);
END;
$$
;
CALL extract_json('{"fName":"Pink","lName":"Panther"}');
Expected out, 2 columns only:
FIRST_NAME LAST_NAME
Pink Panther
Any help is appreciated.
Thanks
The are few issues with the code:
a) resulset contains two column so (res varchar) will not work
b) alias json_data::sting cannot be casted
c) missing ' around input_json, ideally it should be bind parameter
CREATE OR REPLACE PROCEDURE extract_json(input_json varchar)
RETURNS TABLE (col VARIANT, res varchar)
LANGUAGE SQL
AS
$$
DECLARE
qry string;
res resultset;
BEGIN
qry := 'SELECT parse_json('''||:input_json||''') AS json_data, json_data:fName::string';
res := (execute immediate qry);
return table(res);
END;
$$
;
CALL extract_json('{"fName":"Pink","lName":"Panther"}');
Output:
Expected out, 2 columns only:
CREATE OR REPLACE PROCEDURE extract_json(input_json varchar)
RETURNS TABLE (firstName VARCHAR, lastName varchar)
LANGUAGE SQL
AS
$$
DECLARE
qry string;
res resultset;
BEGIN
qry := 'SELECT json_data:fName::string, json_data:lName::string FROM (SELECT parse_json('''||:input_json||''') AS json_data)';
res := (execute immediate qry);
return table(res);
END;
$$;
CALL extract_json('{"fName":"Pink","lName":"Panther"}');
Output:

Can we return a table with about 270 columns on snowflake through a stored procedure using sql? Syntax is below

Can we return a table in Snowflake using sql as language? What is the correct syntax if possible?
create or replace procedure sp()
returns table ()
language sql
as
$$
declare
accountingMonth :=(select dateadd(month,case when day(current_timestamp())<=10 then -1 else 0 end,dateadd(month,0,date_trunc('month',current_date()))));
endmonth :=(select dateadd(month,1,dateadd(month,case when day(current_timestamp())<=10 then -1 else 0 end,dateadd(month,0,date_trunc('month',current_date())))));
currmonth date default accountingMonth;
begin
create or replace temporary table sa as (
select col1,col2, col3,datecol,....col270
from table2
where datecol = :accountingmonth
);
end;
select * from sa;
$$
Yes, it is possible to return table from strored procedure using RESULTSET
CREATE OR REPLACE PROCEDURE sp()
RETURNS TABLE(col1 INTEGER, ...)
LANGUAGE SQL
AS
BEGIN
-- ...
let RESULTSET DEFAULT (select * from sa);
RETURN TABLE(res);
END;

Issues while converting sql server stored procedure to oracle stored procedure

My Sql Server Stored Procedure Is
ALTER PROCEDURE myproc
#iii NVARCHAR(255)
AS
BEGIN
select * from dbo.users where (first_name = #iii OR #iii = '' );
END;
While
By Running it
exec myproc ''
Get All Records
But in oracle
CREATE OR REPLACE PROCEDURE myproc (fname IN STRING, name1 OUT STRING) AS
BEGIN
SELECT "first_name" INTO name1 FROM "users" WHERE ( "first_name" = fname OR fname = '');
END;
But by executing it with '' Parameter Not Found Data.
How do I get all the data?
You have to declare the output variable,
declare
--declare the output variable
v_output varchar2(100);
begin
-- call it
myproc('King', v_output);
-- print it
dbms_output.put_line(v_output);
end;
You can as well declare an exception, cause if the output variable end without value then it will return an error too
Exception:
CREATE OR REPLACE PROCEDURE myproc ( fname IN STRING
, name1 OUT STRING) AS
BEGIN
select First_name
into name1
from hr.employees x
where x.last_name = fname
and rownum = 1;
EXCEPTION
when others then
name1 := null;
END;

building a select statement in oracle using values stored in variables

Is there a way to build a select statement in oracle using values stored in variables?
For example can you do this:
declare
tbl_var varchar2(10) := "map_set";
begin
select count(*) from tbl_var;
end;
Yes there is, using execute immediate:
declare
tbl_var varchar2(10) := 'map_set';
result number;
begin
execute immediate 'select count(*) from '||tbl_var into result; --save result into variable
dbms_output.put_line('Total rows:'||result); --print result
end;
Second way, you can create a function that receives table name as parameter and return the count:
create function get_count(tbl_var varchar2) return number is
result number;
begin
execute immediate 'select count(*) from '||tbl_var into result;
return result;
end;
After create the function you can query it like this:
select get_count('map_set') from dual;

Stored procedure in T-SQL transform to PostgreSQL

I have a stored procedure writen in T-SQL and I want to make it for PostgreSQL but I'm not so familiar with PostgreSQL.
My stored procedure look like this:
CREATE PROCEDURE usp_insert_allocated_time
#fld_project_id INT,
#fld_allocated_time INT
AS
DECLARE #project int;
SET #project = #fld_project_id;
DECLARE #allocated int;
DECLARE #time int;
BEGIN
SET #time = (SELECT SUM(fld_allocated_time)
FROM dbo.tbl_project_timesheet
WHERE fld_project_id =#project)
SET #allocated = (SELECT fld_allocated_days FROM dbo.tbl_project where fld_id = #project);
IF #allocated > #time
BEGIN
INSERT into dbo.tbl_project_timesheet(fld_project_id,fld_allocated_time)
VALUES(#fld_project_id,#fld_allocated_time);
END
ELSE
PRINT 'Not OK';
END
And I have to do something like this, but on line 10 I get this error:
ERROR: invalid input syntax for integer: "293.00"
SQL state: 22P02
Context: PL/pgSQL function
"SA_PRJ".usp_add_timesheet_record_new(integer,integer,numeric,numeric,character varying,character varying) line 10 at assignment
CREATE OR REPLACE FUNCTION "SA_PRJ".usp_add_timesheet_record_new(p_uid integer, p_project_id integer, p_allocated_time numeric, p_achieved_time numeric, p_task_desc character varying, p_obs character varying)
RETURNS void AS
$BODY$
declare alloc_id integer;
declare project integer;
declare allocated integer;
declare allocated_time integer;
BEGIN
project := p_project_id;
allocated_time := (SELECT SUM(fld_allocated_time)
FROM "SD_PRJ".tbl_project_timesheet
WHERE fld_project_id = project);
allocated := (SELECT fld_allocated_days FROM "SD_PRJ".tbl_project where fld_id = project);
if not "SA_ADM".usp_check_permission(p_uid, 'SA_PRJ', 'usp_add_timesheet_record') then
raise exception 'User ID % no have the permission!', p_uid;
end if;
select fld_id into alloc_id from "SD_PRJ".tbl_project_allocation where fld_emp_id = p_uid and fld_project_id = p_project_id;
BEGIN
IF (allocated > allocated_time) THEN
INSERT INTO "SD_PRJ".tbl_project_timesheet(fld_emp_id, fld_project_id, fld_is_allocated,fld_allocated_time, fld_achieved_time, fld_task_desc, fld_obs)
VALUES (p_uid,p_project_id,coalesce(alloc_id,0), p_allocated_time, p_achieved_time,p_task_desc, p_obs);
ELSE
RAISE NOTICE 'Not OK!!';
END IF;
END;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
It's more complex version in PostgreSQL for what I want.
You don't really give enough information to try and fix your problem, but the error message is pretty descriptive. You are trying to put 293.00 into an integer. Here I can reproduce:
DO
$$
DECLARE
i INT;
BEGIN
i := 293.00;
RAISE NOTICE 'i=%', i;
END
$$;
This will raise:
ERROR: invalid input syntax for integer: "293.00"
SQL state: 22P02
Context: PL/pgSQL function inline_code_block line 6 at assignment
You need to change your variable to the same datatype as the data you are trying to assign to it. For example:
DO
$$
DECLARE
i NUMERIC(5, 2);
BEGIN
i := 293.00;
RAISE NOTICE 'i=%', i;
END
$$;
This works and outputs:
NOTICE: i=293.00
Query returned successfully with no result in 14 ms.

Resources