Getting same value for all records in snowflake - snowflake-cloud-data-platform

I have key_value table and key table. I have to load only key from key_value table and insert into key table using snowflake procedure. I have written below code. After executing it i am getting same key value in key table rather all the keys.
create or replace procedure proc_key_load()
returns varchar
language javascript
as
$$
var query=`select key from key_value`;
var ret=snowflake.createStatement( {sqlText: query}).execute();
var length=ret.getRowCount();
var counter=0;
while(counter<length){
ret.next();
var value=ret.getColumnValue(1);
var load_query=`insert into key_load values(` + value +`)`;
var ret=snowflake.createStatement( {sqlText: load_query}).execute();
counter += 1;
}
return 'SUCCESS';
$$

I didn't test it but as I see that you redefine "ret" in the loop. Try with assigning different variable:
create or replace procedure proc_key_load()
returns varchar
language javascript
as
$$
var query=`select key from key_value`;
var ret=snowflake.createStatement( {sqlText: query}).execute();
var length=ret.getRowCount();
var counter=0;
while(counter<length){
ret.next();
var value=ret.getColumnValue(1);
var load_query=`insert into key_load values(` + value +`)`;
var ret2 = snowflake.createStatement( {sqlText: load_query}).execute();
counter += 1;
}
return 'SUCCESS';
$$
Update: I tested the above code and it works. If you just need to copy some data from one table to another, you can just plain SQL right? Something like:
INSERT INTO key_load SELECT key FROM key_value;
Anyway, if you really need to use the above procedure, you can write it in a more efficient way:
create or replace procedure proc_key_load()
returns varchar
language javascript
as
$$
var query=`select key from key_value`;
var ret=snowflake.createStatement( {sqlText: query}).execute();
while(ret.next()){
var value=ret.getColumnValue(1);
var load_query=`insert into key_load values(?)`;
snowflake.createStatement( {sqlText: load_query, binds:[value] }).execute();
}
return 'SUCCESS';
$$;

Related

Create stored procedure that create users in snowflake

I am trying to create a stored procedure in snowflake that create users in snowflake. But I am unable to bind variables.
Here is what I tried using snowflake scripting. I was not successful in creating a version that works
create or replace procedure create_user(user_name varchar, password_value varchar)
returns varchar
language sql
as
$$
begin
create user :USER_NAME password = :password_value;
return 'Completed.';
end;
$$
;
In the above stored procedure, when I use :USER_NAME (I have tried upper and lower case). I get an error saying unexpected :. Password_value seems to work correctly.
I have also tried javascript version
CREATE OR REPLACE PROCEDURE security.create_user_v2(USER_NAME varchar, PASSWORD_VALUE varchar)
RETURNS BOOLEAN
LANGUAGE JAVASCRIPT
AS
$$
var cmd = "create user :1 password = :2;";
var stmt = snowflake.createStatement(
{
sqlText: cmd,
binds: [USER_NAME, PASSWORD_VALUE]
}
);
var result = stmt.execute();
result.next();
return true
$$
;
I get the same here as well, says unexpected :.
This version works, but this is concatenation, i want to avoid this (possible sql injection)
CREATE OR REPLACE PROCEDURE security.create_user_v2(USER_NAME varchar, PASSWORD_VALUE varchar)
RETURNS BOOLEAN
LANGUAGE JAVASCRIPT
AS
$$
var cmd = "create user "+USER_NAME+" password = :1;";
var stmt = snowflake.createStatement(
{
sqlText: cmd,
binds: [PASSWORD_VALUE]
}
);
var result = stmt.execute();
result.next();
return true
$$
;
How do I create a snowflake scripting version or javascript version that bind variables when creating users in stored procedure.
User name must be enclosed with IDENTIFIER in order to use variable:
CREATE OR REPLACE PROCEDURE security.create_user_v2(USER_NAME varchar,
PASSWORD_VALUE varchar)
RETURNS BOOLEAN
LANGUAGE JAVASCRIPT
AS
$$
var cmd = "create user IDENTIFIER(:1) password = :2;";
var stmt = snowflake.createStatement(
{
sqlText: cmd,
binds: [USER_NAME, PASSWORD_VALUE]
}
);
var result = stmt.execute();
result.next();
return true
$$
;
Call:
CALL security.create_user_v2('user1', 'password123');
CALL security.create_user_v2('"user1#x.com"', 'password123');
SHOW USERS;
Snowflake Scripting:
create or replace procedure security.create_user(user_name varchar,
password_value varchar)
returns varchar
language sql
as
$$
begin
create user IDENTIFIER(:USER_NAME) password = :password_value;
return 'Completed.';
end;
$$;

How to bind JavaScript based date column in Snowflake SQL

I am creating snowflake JavaScript based store procedure. How can i refer the date data type variable in snowflake sql.
Here is the sample code:
In the below code ,please suggest how can i use 'dnblatestdt' variable in sql statement.
create or replace procedure test_proc_registration_master_perished_dt(PARAM_REG_SUB_UUID VARCHAR)
returns varchar not null
language javascript
as
$$
/*get latest ingestion_uuid for the given state*/
var step01=`select distinct dnb_applicable_dt,ingestion_uuid from temp_registration_hash_master `;
var statement01=snowflake.createStatement( {sqlText: step01,binds: [PARAM_REG_SUB_UUID]} );
variable1= statement01.execute();
variable1.next();
dnblatestdt=variable1.getColumnValue(1);
ingsuuid=variable1.getColumnValue(2);
/* check if the ingestion is successful or not*/
var step02=`select INGESTION_SUCCESSFUL from FILE_INGESTION_HISTORY where ingestion_uuid=:1 and date=:2::TIMESTAMP_LTZ::DATE`;
var statement02=snowflake.createStatement( {sqlText: step02,binds: [ingsuuid,dnblatestdt]} );
variable2= statement02.execute();
variable2.next();
ingsindc=variable2.getColumnValue(1);
return 'success'
$$
So I wrote a much simpler function that uses a similar pattern to your code:
create or replace procedure test_proc()
returns varchar not null
language javascript
as
$$
var step01 = `SELECT 6::number, '2022-01-27'::timestamp_ntz;`;
var statement01 = snowflake.createStatement( {sqlText: step01} );
results1 = statement01.execute();
results1.next();
ingsuuid = results1.getColumnValue(1);
dnblatestdt = results1.getColumnValue(2);
/* check if the ingestion is successful or not*/
var step02=`SELECT :1 * 2, DATEADD(year,-1, :2::timestamp_ntz);`;
var statement02 = snowflake.createStatement( {sqlText: step02,binds: [ingsuuid , dnblatestdt]} );
results2 = statement02.execute();
results2.next();
ingsindc = results2.getColumnValue(1);
return 'success'
$$
;
and using it works for me:
call test_proc();
TEST_PROC
success
I swapped the order of the reading parameters on the first function, but that should not be a problem.
this makes me thing your casting on the second instance is not working
:2::TIMESTAMP_LTZ::DATE
so I would suggest moving that casting to the first function, which you can test outside the stored procedure, thus.
SELECT DISTINCT dnb_applicable_dt::TIMESTAMP_LTZ::DATE, ingestion_uuid
FROM temp_registration_hash_master
when that is happy, you shouldn't need any casting on the second used of the values.

Snowflake procedure

Basically I have created the notification alert using integrating AWS and Snowflake.
I want to add variable to my select statement. But its not working. So it will be for example "The token of user has expierd (name of the user).
Here is my function
`create or replace external function helloemailworld
(Sender varchar,Receiver Varchar , SUBJECT varchar, BODY_TEXT varchar)
returns variant
api_integration = hellotesting
as 'https://....execute-api.eu-...l-1.amazonaws.com/dev/helloworld';`
and here is my procedure
create or replace procedure Notification()
returns variant
language javascript
EXECUTE AS caller
as
$$
var my_sql_command = "select * from notification";
var statement1 = snowflake.createStatement( {sqlText: my_sql_command} );
var result_set1 = statement1.execute();
while (result_set1.next()) {
var column1 = result_set1.getColumnValue(1);
var column2 = result_set1.getColumnValue(2);
var column3 = result_set1.getColumnValue(3);
var execute = "select helloemailworld('lukasz#gmail.com','lukasz#op.pl','Alert', 'The token of user has expierd' + column1);"
var statement2= snowflake.createStatement( {sqlText: execute} );
var result_set2 = statement2.execute();
}
$$
;
The column 1 is a variable and in notification table first column is also a variable

how to pass variant data into snowflake table using snowflake stored procedure

may i know how to pass variant data into snowflake table using snowflake stored procedure .
CREATE
OR REPLACE PROCEDURE abc(
MY_ID STRING,
P_FILTERS VARIANT
) RETURNS VARIANT
LANGUAGE JAVASCRIPT as $$
try
{
var P_FILTERS=P_FILTERS;
var query=" INSERT INTO abc (SQ_ID,id,\
FILTERS,\
ITERATION)\
VALUES (abc.nextval,\
:1,\
:2,\
0); "
var sql = snowflake.createStatement( {sqlText: query,binds:[MY_ID,P_FILTERS] });
var resultSet = sql.execute();
COMMIT;
}
catch(error)
{
return (error);
}
$$;
can some one help and undestand in letting me know
Thanks,
Nikhil
The solution isn't totally straightforward, but going from variant to string to variant solves the problem:
create or replace temp table variants as
select 'a'::string id, parse_json('{"hello":"world"}') v
;
CREATE
OR REPLACE PROCEDURE insert_variant(
MY_ID STRING,
P_FILTERS VARIANT
) RETURNS VARIANT
LANGUAGE JAVASCRIPT as $$
var query="INSERT INTO variants (id, v) select :1, parse_json(:2); "
var sql = snowflake.createStatement({
sqlText: query
, binds:[MY_ID, JSON.stringify(P_FILTERS)]
});
var resultSet = sql.execute();
$$;
call insert_variant('c', parse_json('{"hello2":"world3"}'))
;
This because
Currently, only JavaScript variables of type number, string, and SfDate can be bound. https://docs.snowflake.com/en/sql-reference/stored-procedures-usage.html#binding-variables
And trying to parse JSON on the VALUES() part of an insert gives you the error "Invalid expression in VALUES clause". But having an INSERT+SELECT solves it.

Retrieve the Variable value and insert into another table

I can retrieve the values of before(0) and after counts(4) from the below statements, but when I make use of those variables (load_cnt_before, load_cnt_after) from the code below and refer them to have the values inserted into a table it says it cant find the variables(refer to error below). How can I use those values to INSERT them into table.
Error: Execution error in stored procedure REC_COUNT_CHECK: SQL compilation error: error line 1 at position 114 invalid identifier 'LOAD_CNT_BEFORE' At Statement.execute, line 25 position 90
Code:
CREATE OR REPLACE PROCEDURE REC_COUNT_CHECK()
RETURNS VARCHAR LANGUAGE JAVASCRIPT
AS $$
/***** Get the Record Count before Refresh ****/
var load_cnt=`SELECT Count(*) as record_cnt from "PLNG_ANALYSIS"."LOADDATA"."LOAD_VERIFICATION" WHERE EXTRACTDATE=Current_date()-1 ;`
var load_cnt_check = snowflake.createStatement({sqlText: load_cnt}).execute();
load_cnt_check.next();
load_cnt_before = load_cnt_check.getColumnValue(1);
/***** Execute the SP ****/
var sp_call = "CALL LOAD_VERIFICATION()"; /***Refreshes data in table LOAD_VERIFICATION***/
var result = snowflake.execute({sqlText: sp_call});
result.next();
var return_msg2 = result.getColumnValue(1);
/***** Check the After Refresh Count ****/
var load_cnt_after=`SELECT Count(*) as record_cnt from "PLNG_ANALYSIS"."HFM"."LOAD_VERIFICATION" WHERE EXTRACTDATE=Current_date() ;`
var load_cnt_check_after = snowflake.createStatement({sqlText: load_cnt_after}).execute();
load_cnt_check_after.next();
load_cnt_after= load_cnt_check_after.getColumnValue(1);
/***** INSERT BEFORE AND AFTER COUNTS INTO LOG TABLE ****/
var insert_status_sp1=`INSERT INTO LOAD_STATUS_LOG_KK values (Current_TIMESTAMP(),1,'LOAD_VERIFICATION','Success','',**load_cnt_before,load_cnt_after**,1);`
var exec_sp1_status = snowflake.createStatement({sqlText: insert_status_sp1}).execute();
exec_sp1_status.next();
return 'Success'
$$;
CALL REC_COUNT_CHECK();
JS variables should be passed into SQL query. The mechanism is called Binding Variables
var insert_status_sp1=`INSERT INTO LOAD_STATUS_LOG_KK values (Current_TIMESTAMP(),1,'LOAD_VERIFICATION','Success','',:1,:2,1);`
var exec_sp1_status = snowflake.createStatement(
{sqlText: insert_status_sp1,binds:[load_cnt_before,load_cnt_after]}
).execute();

Resources