How to write multi line query in snowflake scripting in stored procedure - stored-procedures

create or replace procedure create_src_table()
returns table (name varchar, age number(10,0),dob date)
language sql as
$$
declare
create_query varchar;
res resultset;
begin
create_query := `CREATE TEMPORARY TABLE SRC_TEMP_TBL AS SELECT * FROM
(WITH CTE_1 AS (SELECT * FROM "DB"."DW"."USER_TBL" WHERE name='rahul'),
CTE_2 AS (SELECT * FROM CTE_1 WHERE CAST(DOB AS DATE)<2000-05-01)
SELECT name,age,dob FROM CTE_2 limit 10)`;
res := (execute immediate : create_query);
return table(res);
end;
$$;
call create_src_table();
Could someone please help in how to write multiline sql query. I found few answers that indicate using backtick in javascript but not sure how to achieve it in sql.

Multi-statement SQL should be wrapped inside BEGIN ... END block:
EXECUTE IMMEDIATE 'BEGIN
statement1;
statement2;
...
END;';
Sample:

Related

Set a variable value in stored procedure and use in following query

How can I set a variable in stored procedure and use it in following query to be executed.
create or replace procedure sp1()
returns table (dealer_id varchar, dealershipgroup_name varchar)
language sql
as
$$
declare
create_query varchar;
res resultset;
MISSING_DEALER NUMBER(38,0) default 0;
begin
MISSING_DEALER := 100;
select_query := 'WITH CTE AS(
SELECT dealer_id,
CASE WHEN dealer_id=:MISSING_DEALER then \'Abc\'
WHEN dealershipgroup IS NULL then \'\'
ELSE dealershipgroup end as dealershipgroup FROM TBL )
select * from CTE';
res:= (execute immediate : select_query);
return table(res);
end;
$$;
call sp1();
Could someone please suggest how can I use MISSING_DEALER in the query. I am currently getting the following error
Uncaught exception of type 'STATEMENT_ERROR' on line 28 at position 9 : SQL compilation error: error line 8 at position 26 Bind variable :MISSING_DEALER not set
You need to concatenate the string parts of your SQL statement with the variable. This is covered in the documentation if you look at the end of the section here

Snowflake stored procedure - sql - binding variables in the from clause

Please help in binding the stored procedure argument into the sql statement given
create or replace procedure test(table_name varchar)
returns integer
language sql
as
$$
select count(*) from ?
$$
You want to use an OBJECT INDENTIFIER
create or replace procedure test(table_name varchar)
returns integer
language sql
as
declare
c number;
begin
select count(*) into c from identifier(:table_name);
return c;
end;
call test('test.test.testo');
TEST
3
Using TABLE():
create or replace procedure test(table_name varchar)
returns integer
language sql
as
declare
c number;
begin
select count(*) into c from table(:table_name);
return c;
end;
CALL test('tab');
-- 0

Convert Procedure from Oracle to DB2, Error when try to update table on runtime

Hello DB2 Experts I need your assistance in converting below Procedure to something more dynamic.
We have to update multiple sequences with max of id column for each table.
CREATE PROCEDURE mySchema.UPDATE_SEQUENCE ( )
DYNAMIC RESULT SETS 1
MODIFIES SQL DATA
----------------------------------------------------------------------
-- SQL Stored Procedure
----------------------------------------------------------------------
P1: BEGIN
DECLARE counter BIGINT;
DECLARE q VARCHAR(500);
set (counter) = (select max(N_PRI_KEY) from mySchema.myTable);
set q = 'alter sequence mySchema.mySequence RESTART WITH ' || counter;
EXECUTE IMMEDIATE q;
END P1
#
This is what I have written from the above code:
Here I want N_PRI_KEY to be dynamic and mySchema.myTable to be updated on run time with the values from the table.
CREATE OR REPLACE PROCEDURE getText ()
LANGUAGE SQL
DYNAMIC RESULT SETS 1
BEGIN
DECLARE maxval INTEGER DEFAULT 0;
CALL DBMS_OUTPUT.PUT( 'a' );
FOR vrows AS
SELECT NAME, SEQUENCENAME, TBNAME FROM MAXSEQUENCE WHERE SEQUENCENAME='ASSETSEQ'
DO
SELECT MAX(vrows.NAME) INTO maxval FROM vrow.TBNAME; -- This is where I am getting error.
EXECUTE IMMEDIATE 'ALTER SEQUENCE '||vrows.SEQUENCENAME||' RESTART WITH '|| maxval;
END FOR;
END#
This is the error that I am getting when I try to create the Procedure.
DB21034E The command was processed as an SQL statement because it was not a
valid Command Line Processor command. During SQL processing it returned:
SQL0204N "VROW.TBNAME" is an undefined name. LINE NUMBER=18. SQLSTATE=42704
When I run this line it works and inserts the max value in the TEMPOUTPUT table.
execute immediate 'INSERT INTO TEMPOUTPUT VALUES (select max('||vrow.NAME||') from '||vrow.TBNAME||')';
I have tried doing this but it did not work.
execute immediate 'ALTER SEQUENCE '||SEQUENCENAME||' RESTART WITH select max('||vrow.NAME||') from '||vrow.TBNAME;
Just for Reference - This is a procedure which is written in Oralce which is doing something similar.
declare
maxval int;
seqval int;
begin
for i in ( select ucc.column_name, s.sequence_name, uc.table_name
from user_cons_columns ucc,
user_constraints uc,
user_sequences s
where uc.constraint_name = ucc.constraint_name
and uc.constraint_type = 'P'
and ucc.position = 1
and s.sequence_name = 'SEQ_'||uc.table_name
)
loop
execute immediate 'select max('||i.column_name||') from '||i.table_name into maxval;
execute immediate 'select '||i.sequence_name||'.nextval from dual' into seqval;
dbms_output.put_line(maxval||','||seqval);
if maxval > seqval then
execute immediate 'alter sequence '||i.sequence_name||' increment by '|| ( maxval - seqval );
execute immediate 'select '||i.sequence_name||'.nextval from dual' into seqval;
execute immediate 'alter sequence '||i.sequence_name||' increment by 1';
execute immediate 'select '||i.sequence_name||'.nextval from dual' into seqval;
dbms_output.put_line(maxval||','||seqval);
end if;
end loop;
end;
Try the following instead of the row with SELECT MAX(...) where you get the error:
PREPARE S1 FROM 'SET ? = (SELECT MAX(' || vrows.NAME || ') FROM ' || vrows.TBNAME || ')';
EXECUTE S1 INTO maxval;

Oracle - Dynamic select procedure

I need a stored procedure with dynamic select statement, in my case only adding desired column names in select. This is what I created, but I'm not sure If It's safe for SQL injections:
CREATE OR REPLACE PROCEDURE MySchema.Search(
columns IN VARCHAR2,
res_out OUT SYS_REFCURSOR)
IS
BEGIN
OPEN res_out FOR
'SELECT ' || columns ||' FROM MySchema.Table1';
END Search;
Is this fine or is It not safe ? When reading all examples I haven't noticed anything easy as this, but It works. If It's not safe for SQL injections, please show me how I should do It. Thanks for help in advance !
I will suggest to you use your PL/SQL like this: in the below PL/SQL it ensures that, if any of the SQL Injection statement is trying to invoke it will stop.
CREATE OR REPLACE PROCEDURE MySchema.Search(
columns IN VARCHAR2,
res_out OUT SYS_REFCURSOR)
IS
v_columns VARCHAR2(4000);
BEGIN
select listagg(column_name,',') within group(order by 1)
INTO v_columns
from all_tab_columns
where owner = 'MYSCHEMA'
and table_name = 'TABLE1'
and column_name in (select regexp_substr(columns,'[^,]+', 1, level)
from dual
connect by regexp_substr(columns, '[^,]+', 1, level) is not null
);
OPEN res_out FOR
'SELECT ' || v_columns ||' FROM MySchema.Table1';
END Search;

Inserting values in to netezza using a stored procedure

I'm working with netezza database and have a requirement to insert a Y flag for stores in California. I wrote the below procedure
CREATE OR REPLACE PROCEDURE MY_NEW_PROCEDURE() RETURNS BOOL
EXECUTE AS OWNER LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
rec RECORD;
BEGIN
FOR rec in SELECT * from test_table
LOOP
if rec.state_code ='CA'
EXECUTE IMMEDIATE 'INSERT INTO test_table (california_stores)' || 'values('y')';
END LOOP;
END;
END_PROC;
when I call the procedure using call MY_NEW_PROCEDURE() I get an error at line EXECUTE IMMEDIATE. I'm not sure what change I need to make here.
Don't know about netezza, but below is the procedure I used to test this (using SQL developer).
Works fine for me, although it would make more sense to update the row to set california_stores to 'Y'rather than insert a new row with california_stores = 'Y' for each calafornia store that you have.....
CREATE OR REPLACE PROCEDURE "MY_NEW_PROCEDURE" as
rec test_table2%rowtype;
BEGIN
FOR rec in (SELECT * from test_table2) LOOP
if rec.state_code = 'CA' then
EXECUTE IMMEDIATE 'INSERT INTO test_table2 (california_stores)' || 'values(''y'')';
end if;
END LOOP;
END;
You didn't post the second error, but it looks to me like your insert statement isn't going to do what you want anyway. If the rec variable contains the attribute state_code and you're inserting a single value to test_table then the record will simply be empty except for a 'Y' in california_stores.
I'm going to guess that you're getting an error now either because of the spacing in the insert statement insert into test_table (california_stores)values('y') or because you didn't terminate the execute statement with a semicolon. The plsql for that line should be
execute immediate 'insert into test_table (california_stores) values (''y'');';

Resources