Javascript function in snowflake to append tablename with current date - javascript

I have recently started to use snowflake and have been stuck at this issue:
I want to clone a table called AB_USER to AB_USER_(current_date). I have written following code to accomplish this:
CREATE or replace PROCEDURE backup_proc()
RETURNS VARCHAR
LANGUAGE javascript
AS
$$
var tab_name = `AB_USER_BCK_2020_`+ current_date();
stat = `create or replace table staging.` + tab_name + ` clone staging.AB_USER`;
var rs = snowflake.execute( { sqlText: stat} );
return 'Done.';
$$;
The problem is I cannot find appropriate function to get current date. Snowflake provides a JS environment but I don't know which function to use to get current date.
I am very new to snowflake so any help in this will be much appreciated.
Thanks.

CURRENT_DATE is an SQL command, so you need to call it as SQL statement with snowflake.execute.
As I see, you want to get values of month and day from current date, so you can use the following procedure:
CREATE or replace PROCEDURE backup_proc()
RETURNS VARCHAR
LANGUAGE javascript
AS
$$
var curdate = snowflake.execute( { sqlText: "SELECT TO_CHAR(CURRENT_DATE,'MMDD') as curdate"} );
curdate.next();
var tab_name = "AB_USER_BCK_2020_"+ curdate.getColumnValue('CURDATE');
var stat = "create or replace table staging." + tab_name + " clone staging.AB_USER";
var rs = snowflake.execute( { sqlText: stat} );
return "Done.";
$$
;

Related

Dynamic SQL using Snowflake SQL Stored Procedure

I want to be able to update rows of data in a set list of tables for certain columns within those tables.
Basically something like this;
TABLE_NAME COL1
TABLE1 NAME
TABLE2 ADDRESS
select * from TABLE1;
Aidan
Select * from TABLE2;
Ireland
So something like the query below as a stored procedure that would gather all the tables and columns to be altered and update the records accordingly.
update $TABLE_NAME set $COL1 ='*' where ID in (select ID FROM EXTERNAL_TABLE)
Any help greatly appreciated.
Tried messing around with this sample but got nowhere when I try build on it
CREATE OR REPLACE PROCEDURE DATA_MASKING("P_TABLE_NAME" VARCHAR(16777216))
RETURNS VARCHAR(16777216)
LANGUAGE JAVASCRIPT
EXECUTE AS OWNER
AS '
// Define query String
var sql_command = "UPDATE " + P_TABLE_NAME + " SET IND_ADDR1 = NULL;"
//Prepare SQL statement
var stmt = snowflake.createStatement({sqlText: sql_command});
//Execute SQL Statement
var rs = stmt.execute();
return ''Table truncated successfully.''
';
call PERSISTENT_DATA_MASKING('TEST_TABLE');
The Proc you had given works. Just needs few amends which you must have been able to do. So, not sure what exactly is the question.
CREATE OR REPLACE PROCEDURE DATA_MASKING("P_TABLE_NAME" VARCHAR(16777216), "P_COLUMN_NAME" VARCHAR(16777216))
RETURNS VARCHAR(16777216)
LANGUAGE JAVASCRIPT
EXECUTE AS OWNER
AS '
// Define query String
var sql_command = "UPDATE " + P_TABLE_NAME + " SET " + P_COLUMN_NAME + " = ''x'';"
//Prepare SQL statement
var stmt = snowflake.createStatement({sqlText: sql_command});
//Execute SQL Statement
var rs = stmt.execute();
return ''successful''
';
CALL DATA_MASKING('SCHEMA.TABLE_NAME','COLUMN_NAME');
SELECT * FROM SCHEMA.TABLE_NAME;

Snowflake Stored Procedures to generate unique IDs and then insert values into a table

I am using Snowflake stored procedures to try and log errors as they occur. The current stored proc has an if/else statement, but I'm just trying to get one section working for now since the code is the more or less the same with variations to the SQL statements.
create or replace Procedure PLog(
PName varchar,
CName varchar,
PType varchar)
returns varchar
not null
language javascript
AS
$$
var cyc_id_sql = `SELECT case when count(CycleId) > 0 then max(CycleID) + 1 else 1 end as CycleId from SCHEMA.TABLE1 where CycleName='${CName}'`;
var cycle_id_create = snowflake.createStatement({ sqlText: cyc_id_sql});
var cycleid = cycle_id_create.execute();
var p_id_sql = `Select case when count(ProcessId) > 0 then max(ProcessID) + 1 else 1 end as ProcessId from SCHEMA.TABLE2 where ProcessName='${PName}'`;
var p_id_create = snowflake.createStatement({ sqlText: p_id_sql});
var processid = p_id_create.execute();
var insertValuesText = `INSERT INTO SCHEMA.TABLE
(
ProcessLogId
,CycleId
,ProcessId
,CycleName
,ProcessName
,ProcessType
,ProcessStatus
,StartTime)
VALUES
(default,${cycleid},${processid},'${value3}','${value4}','${value5}','Started',current_timestamp )`;
var insertValues = snowflake.createStatement({ sqlText: insertValuesText});
insertValues.execute();
$$
When I call this I get the error:
SQL compilation error: syntax error line 12 at position 28 unexpected 'Object'. syntax error line 12 at position 44 unexpected 'Object'. At Statement.execute, line 22 position 13
I think the issue is that the cycle and process statements create a Javascript object instead of the desired value. The desired value being the unique ID. When I run the SQL separately with an empty database I get 1, which is expected so I know the SELECT statements work. When I run and then call:
create or replace Procedure PLog(
PName varchar,
CName varchar,
PType varchar)
returns varchar
not null
language javascript
AS
$$
var cyc_id_sql = `SELECT case when count(CycleId) > 0 then max(CycleID) + 1 else 1 end as CycleId from SCHEMA.TABLE1 where CycleName='${CName}'`;
var cycle_id_create = snowflake.createStatement({ sqlText: cyc_id_sql});
var cycleid = cycle_id_create.execute();
return cycleid
$$
I get [object Object]. I'm not that familiar with JavaScript so any help would be appreciated. I think the issue is that my variables generate instances of an object instead of a usable value for the SQL statement, I just don't know how to fix the issue. Thank you!
when you execute a statement var processid = p_id_create.execute(); processid is the result set, not the actual value you want. you need to fetch it
so here is some example from the doc's
CREATE OR REPLACE PROCEDURE right_bind(TIMESTAMP_VALUE VARCHAR)
RETURNS BOOLEAN
LANGUAGE JAVASCRIPT
AS
$$
var cmd = "SELECT CURRENT_DATE() > TO_TIMESTAMP(:1, 'YYYY-MM-DD HH24:MI:SS')";
var stmt = snowflake.createStatement(
{
sqlText: cmd,
binds: [TIMESTAMP_VALUE]
}
);
var result1 = stmt.execute();
result1.next();
return result1.getColumnValue(1);
$$
;
so your small example should be:
create or replace Procedure PLog(
PName varchar,
CName varchar,
PType varchar)
returns varchar
not null
language javascript
AS
$$
var cyc_id_sql = `SELECT case when count(CycleId) > 0 then max(CycleID) + 1 else 1 end as CycleId from SCHEMA.TABLE1 where CycleName='${CName}'`;
var cycle_id_create = snowflake.createStatement({ sqlText: cyc_id_sql});
var result1 = cycle_id_create.execute();
result1.next();
var cycleid result1.getColumnValue(1);
return cycleid
$$
You are correct that it's returning a JavaScript object. As Simeon notes, this is returning a resultSet. If you're expecting a query to return a scalar (single row with a single column) you can use inline code to get it. However, it will not be modular and harder to read than modular code. This is a great example of where a helper function helps.
For example:
create or replace procedure TEST()
returns string
language javascript
as
$$
var my_scalar = getScalar("select C_NAME from SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.CUSTOMER limit 1");
return my_scalar;
function getScalar(sql){
cmd = {sqlText: sql};
stmt = snowflake.createStatement(cmd);
var rs;
rs = stmt.execute();
rs.next();
return rs.getColumnValue(1);
}
$$;
You can then use the getScalar helper function to collect scalar values you need. If you're only doing it once it won't matter too much. If you're collecting a few or dozens, then it will keep the code modular, compact, and more readable.

Stored Procedure Snowflake - time formatting issue

var get_end_time = "select CURRENT_TIME()";
var time_sql = {sqlText: get_end_time};
var time_create = snowflake.createStatement(time_sql);
var time_exec_end = time_create.execute();
time_exec_end.next();
var end_time = time_exec_end.getColumnValue(1);
I have this code above in a JavaScript stored procedure in snowflake, this query produces: 11:27:35.181000000
How can I strip this to only give me 11:27:35?
JavaScript Procedure is returning type as string,
so value cannot be interpreted in snowflake as time
or to apply time-base formats.
Code without any formatting for time -
CREATE OR REPLACE PROCEDURE test_time()
RETURNS STRING
LANGUAGE javascript
AS
$$
var get_end_time = "select CURRENT_TIME()";
var time_sql = {sqlText: get_end_time};
var time_create = snowflake.createStatement(time_sql);
var time_exec_end = time_create.execute();
time_exec_end.next();
var end_time = time_exec_end.getColumnValue(1);
return end_time;
$$
;
call test_time();
TEST_TIME
06:20:47.250000000
Use TO_CHAR to get desired format and return same.
CREATE OR REPLACE PROCEDURE test_time()
RETURNS STRING
LANGUAGE javascript
AS
$$
var get_end_time = "select to_char(CURRENT_TIME())";
var time_sql = {sqlText: get_end_time};
var time_create = snowflake.createStatement(time_sql);
var time_exec_end = time_create.execute();
time_exec_end.next();
var end_time = time_exec_end.getColumnValue(1);
return end_time;
$$
;
call test_time();
TEST_TIME
06:27:50
JavaScript does not have a date data-type.
If we are using SQL based procedure which returns datetype date/timestamp,
then its interpretation is as per set format.
In below code there are no format functions applied.
create or replace procedure test_time()
returns date
language sql as
$$
begin
return (select current_timestamp());
end;
$$
;
alter session set timestamp_output_format='hh24:mi:ss.sss';
call test_time();
TEST_TIME
07:03:48.48S
alter session set timestamp_output_format='hh24:mi:ss.ff';
call test_time();
TEST_TIME
07:05:07.236000000
alter session set timestamp_output_format='hh24:mi:ss';
call test_time();
TEST_TIME
07:05:39

How to pass and call Snowflake stored procedure date argument in underlying SELECT statement as a column

I am fairly new to snowflake working on a stored procedure having date as a parameter, the same parameter will be used in SELECT statement to work as additional column in result set.
Below is the code:
CREATE OR REPLACE PROCEDURE test1 (TEST_DATE VARCHAR)
RETURNS VARCHAR NOT NULL
LANGUAGE javascript
EXECUTE AS CALLER
AS
$$
var prod = TEST_DATE;
var sql_stmt = `select
ID
,Value
,getvariable('PROD') as TestDate
, to_varchar(CURRENT_TIMESTAMP()) CreateDate
from
Table;`;
var statement = snowflake.createStatement( {sqlText:sql_stmt} );
var rs = statement.execute();
rs.next(1);
//return rs.getColumnValue(1);
return rs.getColumnValue(3);
$$;
Calling above procedure as
CALL test1('2022-02-22');
Returning error as "NULL result in a non-nullable column".
Please suggest how can I use the argument as column name in select.
Thank You.
Binding Variables:
Binding a variable to a SQL statement allows you to use the value of the variable in the statement.
CREATE OR REPLACE PROCEDURE test1 (TEST_DATE VARCHAR)
RETURNS VARCHAR NOT NULL
LANGUAGE javascript
EXECUTE AS CALLER
AS
$$
var sql_stmt = `select
ID
,Value
, :1 as TestDate
, to_varchar(CURRENT_TIMESTAMP()) AS CreateDate
from Table;`;
var statement = snowflake.createStatement( {sqlText:sql_stmt, binds: [TEST_DATE]} );
var rs = statement.execute();
...
$$;
I think Binding like mentioned above is the more proper method, but you could also use string formatting its a bit more readable.
CREATE OR REPLACE PROCEDURE test1 (TEST_DATE VARCHAR)
RETURNS VARCHAR NOT NULL
LANGUAGE javascript
EXECUTE AS CALLER
AS
$$
var prod = TEST_DATE;
var sql_stmt = `select
ID
,Value
,'${TEST_DATE}' as TestDate
, to_varchar(CURRENT_TIMESTAMP()) CreateDate
from
Table;`;
var statement = snowflake.createStatement( {sqlText:sql_stmt} );
var rs = statement.execute();
rs.next(1);
//return rs.getColumnValue(1);
return rs.getColumnValue(3);
$$;

Converting EXECUTE Statements from Azure SQL to Snowflake

I'm trying to convert the below Azure SQL stored procedure to Snowflake. But I couldn't find an alternative for the EXEC statement yet:
CREATE PROC SAMPLE_PROC
AS
BEGIN
DECLARE #BusinessUnitKey INT=(SELECT BusinessUnitKey FROM BusinessUnit WHERE BusinessUnitName='ABC') ;
DECLARE #LoadDate DATETIME= (SELECT Cast(GETUTCDATE() as Date)) ;
DECLARE #DataLoadLogKey INT = (
SELECT MAX(DataLoadLogKey)
FROM DataLoadLog
WHERE BusinessUnitKey = #BusinessUnitKey
)
,#TableName VARCHAR(100) = 'ProductType'
,#StoredProcName VARCHAR(100) = (object_name(##procid))
,#StarDateTime DATETIME = #LoadDate
,#EndDateTime DATETIME = NULL
,#Status VARCHAR(100) = 'In Progress'
,#LoadDescription VARCHAR(1000) = 'Loading Data' ;
EXEC dbo.usp_procedure #DataLoadLogKey = #DataLoadLogKey
,#TableName = #TableName
,#StoredProcName = #StoredProcName
,#StarDateTime = #StarDateTime
,#EndDateTime = NULL
,#Status = #Status
,#LoadDescription = #LoadDescription ;
END;
Could anyone provide the corresponding execute statement in Snowflake?
Take a look at the Working with Stored Procedures in documentation.
This is a rough stub that should compile.
I cant test the code, as I dont have ddl for your tables or data to validate, but this should give you a good start.
Best Regards.
CREATE OR REPLACE PROCEDURE SAMPLE_PROC()
returns VARCHAR not null
language javascript
as
$$
var businessUnitKey , loadDate, dataLoadLogKey, sql, statement, rs, message ;
message= "FAILED";
// get business unit key
sql = `SELECT BusinessUnitKey FROM BusinessUnit WHERE BusinessUnitName='ABC'`;
statement = snowflake.createStatement({sqlText: sql});
result_set = statement.execute();
while (result_set.next()) {
businessUnitKey = result_set.getColumnValue(1);
}
// get load date
sql = `SELECT Cast(SYSDATE() as Date)`;
statement = snowflake.createStatement({sqlText: sql});
result_set = statement.execute();
while (result_set.next()) {
loadDate = result_set.getColumnValue(1);
}
//return loadDate
sql = `SELECT MAX(DataLoadLogKey)
FROM DataLoadLog
WHERE BusinessUnitKey = ` + businessUnitKey + `;`
statement = snowflake.createStatement({sqlText: sql});
result_set = statement.execute();
while (result_set.next()) {
dataLoadLogKey = result_set.getColumnValue(1);
}
var TableName = 'ProductType'
,StoredProcName = 'SAMPLE_PROC()'
,StarDateTime = LoadDate
,EndDateTime = NULL
,Status = 'In Progress'
,LoadDescription = 'Loading Data' ;
sql = `CALL dbo.usp_procedure(:1,:2,:3,:4,:5,:6,:7); `
statement = snowflake.createStatement({
sqlText: sql,
binds: [dataLoadLogKey,TableName,StoredProcName,StarDateTime,EndDateTime,Status,LoadDescription]
});
message= "SUCCESSFUL";
return message;
$$;
call SAMPLE_PROC();
Snowflake stored procedures are written in JavaScript, which can execute SQL statements by calling a JavaScript API. This API is similar to, but not identical to, the APIs in Snowflake connectors and drivers (Node.js, JDBC, Python, etc.).
Details: https://docs.snowflake.com/en/sql-reference/stored-procedures-usage.html#implementation-and-api
You would be able to find a couple of code examples:
https://docs.snowflake.com/en/sql-reference/stored-procedures-usage.html#examples

Categories