USE DATABASE in stored procedure - snowflake-cloud-data-platform

I am trying to set my database inside the stored procedure, but getting errors, Any advice? Thanks in advance
Below code return error "Unsupported statement type 'USE'."
CREATE PROCEDURE PROC_TEST()
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
AS
$$
try{
var my_sql_command = "USE DATABASE EDWH_DEV";
var statement1 = snowflake.createStatement( {sqlText: my_sql_command} );
statement1.execute();
result = "Succeeded";
}
catch (err) {
result = "Failed: Code: " + err.code + "\n State: " + err.state;
result += "\n Message: " + err.message;
result += "\nStack Trace:\n" + err.stackTraceTxt;
}
return result;
$$;
CALL PROC_TEST();

You need to include line, On which privilege the procedure need to execute:
Include line: execute as caller It will work
CREATE or replace PROCEDURE PROC_TEST()
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
execute as caller
AS
$$
try{
var my_sql_command = "USE DATABASE GCP";
var statement1 = snowflake.createStatement( {sqlText: my_sql_command} );
statement1.execute();
result = "Succeeded";
}
catch (err) {
result = "Failed: Code: " + err.code + "\n State: " + err.state;
result += "\n Message: " + err.message;
result += "\nStack Trace:\n" + err.stackTraceTxt;
}
return result;
$$;

Related

Invalid Identifier when passing a string into sql query in snowflake

I have a stored procedure which takes a string(SCHEMA_NAME) as a parameter
It then puts this string name into a query
The problem I am facing is when I pass the parameter into the sql query I get a
Invalid identifier error
Below is my code and what I have tried
CREATE OR REPLACE PROCEDURE "CREATE_SCHEMA"("SCHNAME" VARCHAR(16777216))
RETURNS VARCHAR(16777216)
LANGUAGE JAVASCRIPT
COMMENT='Creates schemas'
EXECUTE AS CALLER
AS
$$
var v_sqlCode = "select * from dbschemas where name = " + "''" + SCHNAME + "''";
try{
var sqlStmt = snowflake.createStatement({sqlText:v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
$$;
I have tried writing my sql query in three ways
1. var v_sqlCode = `select * from dbschemas where name = `+ SCHNAME;
2. var v_sqlCode = "select * from dbschemas where name = " + "''" + SCHNAME + "''"
3.var v_sqlCode = `SELECT * FROM DBSCHEMAS WHERE NAME = {$SCHENAME}`
The way in which I call the stored procedure is as follows : CALL CREATE_SCHEMA('SCHEMA_NAME');
Any help would be greatly appreciated.
It is recommended to parametrize query to be executed instead of concatenating the SQL query string.
More info: Binding variables
CREATE OR REPLACE PROCEDURE CREATE_SCHEMA(SCHNAME VARCHAR(16777216))
RETURNS VARCHAR(16777216)
LANGUAGE JAVASCRIPT
COMMENT='Creates schemas'
EXECUTE AS CALLER
AS
$$
var v_sqlCode = "select * from dbschemas where name = ?";
try{
var sqlStmt = snowflake.createStatement({sqlText:v_sqlCode, binds:[SCHNAME]});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
$$;
Call:
CALL CREATE_SCHEMA('SCHEMA_NAME');

How to pass a stored procedure as a parameter in snowflake

I have a stored procedure which takes the name of another stored procedure to call on it and with the parameters
However when I try to execute this stored procedure I get an error
What am I doing wrong? From my code below I think I know how to call on a passed stored procedure however I am wondering if it is my syntax that is incorrect.
CREATE OR REPLACE PROCEDURE "ADMINDB"."TOOLKIT".LOG_PROCEDURES("P_PROCEDURE_NAME" VARCHAR, "P_PROCEDURE_PARAMETERS" VARCHAR)
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
COMMENT='Inserts into the table PROCEDURE_LOGGING information about the last runned procedure'
EXECUTE AS CALLER
AS
$$
var v = P_PROCEDURE_PARAMETERS;
var v_sqlCode;
if(P_PROCEDURE_PARAMETERS.length > 0){
v_sqlCode = `CALL ` + P_PROCEDURE_NAME + `(` + P_PROCEDURE_PARAMETERS + `)`;
}else{
return "there was no parameter passed";
}
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
return "success!";
$$;
CREATE OR REPLACE PROCEDURE "ADMINDB"."TOOLKIT".TESTFORLOG("P" VARCHAR)
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
COMMENT='Inserts into the table PROCEDURE_LOGGING information about the last runned procedure'
EXECUTE AS CALLER
AS
$$
var v_sqlCode = 'CREATE TABLE ' + P + `(name varchar)`;
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
return "success!";
$$;
CALL ADMINDB.TOOLKIT.LOG_PROCEDURES('TESTFORLOG','P');
Combining all of the above comments, here are updated stored procedures which are working when I test here on my dev account.
Notes:
be careful with the context and use fully qualified names where possible if doing cross schema/database object references
review your query history when debugging
backticks are awesome for SQL, I have one sample with and one without in the below
I like having the SQL in one block (with backticks) and then doing the replace, as illustrated.
CREATE OR REPLACE PROCEDURE sp_stacko_1(p1 varchar, p2 varchar)
RETURNS VARCHAR
LANGUAGE javascript
EXECUTE AS caller
AS
$$
var p_procedure_name = P1;
var p_params = P2;
if(p_params.length > 0) {
v_sqlCode = `
CALL <p_procedure_name>('<p_params>')
`;
v_sqlCode = v_sqlCode.replace("<p_procedure_name>", p_procedure_name);
v_sqlCode = v_sqlCode.replace("<p_params>", p_params);
}
else {
return "there was no parameter passed";
}
try {
snowflake.execute({sqlText: v_sqlCode});
}
catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
return "success!";
$$;
CREATE OR REPLACE PROCEDURE sp_stacko_2(p3 varchar)
RETURNS VARCHAR
LANGUAGE javascript
EXECUTE AS caller
AS
$$
var p_table_name = P3;
var v_sqlCode = "CREATE TABLE <table_name> (name varchar)";
v_sqlCode = v_sqlCode.replace("<table_name>", p_table_name);
try {
snowflake.execute({sqlText: v_sqlCode});
}
catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt + v_sqlCode;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
return "success!";
$$;
CALL sp_stacko_1('sp_stacko_2','P');

Creating a temp table in stored procedure with SQL and Snowflake

I have a stored procedure which gets the session variables
in snowflake. I want to store these variables in a temporary table
so then I can use it later on.
My logic works but I am unable to write the syntax correctly. Any help would be greatly appreciated.
Here is my code
CREATE OR REPLACE PROCEDURE GET_CONTEXT()
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
COMMENT = 'Saves current database and current schema in an array'
EXECUTE AS CALLER
AS
$$
var arr_context = [];
v_sqlCode = "SELECT CURRENT_DATABASE(), CURRENT_SCHEMA()";
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
var v_sqlCode = "CREATE TEMPORARY TABLE TEMP_HOLDER (DATABASE VARCHAR(16777216), SCHEMA VARCHAR(16777216))";
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS2 = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
v_sqlCode = "INSERT INTO TEMP_HOLDER(DATABASE, SCHEMA)
VALUES(" + sqlRS.getColumnValue(1) + ", "+sqlRS.getColumnValue(2)+")";
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + sqlRS.getColumnValue(1);
errMessage += "\nStack Trace:\n" + err.stackTraceTxt;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
$$;
CALL GET_CONTEXT();
This simplifies it. It also changes the column names from DATABASE and SCHEMA, which are reserved keywords, by prefixing with THE_ such as THE_DATABASE.
CREATE OR REPLACE PROCEDURE GET_CONTEXT()
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
COMMENT = 'Saves current database and current schema in an array'
EXECUTE AS CALLER
AS
$$
let v_sqlCode = "create or replace temp table TEMP_HOLDER as select current_database() as THE_DATABASE,current_schema() as THE_SCHEMA";
try{
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + sqlRS.getColumnValue(1);
errMessage += "\nStack Trace:\n" + err.stackTraceTxt;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
$$;

Obtaining column name from array of strings and using it to alter SQL Table

I am writing a stored procedure in SQL which accepts a String. The string contains a list of column names which contain the column name and the type
ex) "NAME VARCHAR, AGE NUMBER"
ALTER TABLE T1
ADD COLUMN NAME VARCHAR
I am working with Snowflake
My logic is correct, however I am struggling to properly write the syntax
In the code below, the alter table statement with the array is where I am stuck
Any help would be greatly appreciated
CREATE OR REPLACE PROCEDURE ADD_COLUMNS_CONTEXTUAL_ATTRIBUTES("P_COL_NAME_SPACE_TYPE" VARCHAR(16777216))
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
COMMENT = 'Turns column string list into array'
EXECUTE AS CALLER
AS
$$
var arr = [];
var v_storing_passed_parameter = P_COL_NAME_SPACE_TYPE;
arr = v_storing_passed_parameter.split(',');
for (i = 0; i < arr.length; i++){
try{
var v_sqlCode = ***`ALTER TABLE CONTEXTUAL_ATTRIBUTES
ADD COLUMN ' + arr[i];***
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
};
return "success";
$$;
CALL ADD_COLUMNS_CONTEXTUAL_ATTRIBUTES('AGE NUMBER, NAME VARCHAR');
Here you go:
CREATE OR REPLACE PROCEDURE ADD_COLUMNS_CONTEXTUAL_ATTRIBUTES("P_COL_NAME_SPACE_TYPE" VARCHAR(16777216))
RETURNS VARCHAR
LANGUAGE JAVASCRIPT
COMMENT = 'Turns column string list into array'
EXECUTE AS CALLER
AS
$$
var arr = [];
var v_storing_passed_parameter = P_COL_NAME_SPACE_TYPE;
arr = v_storing_passed_parameter.split(',');
for (i = 0; i < arr.length; i++){
try{
var v_sqlCode = `ALTER TABLE CONTEXTUAL_ATTRIBUTES ADD COLUMN ${arr[i]}`;
var sqlStmt = snowflake.createStatement({sqlText : v_sqlCode});
var sqlRS = sqlStmt.execute();
}catch(err){
errMessage = "Failed: Code: " + err.code + "\n State: " + err.state;
errMessage += "\n Message: " + err.message + v_sqlCode;
errMessage += "\nStack Trace:\n" + err.stackTraceTxt;
throw 'Encountered error in executing v_sqlCode. \n' + errMessage;
}
};
return "success";
$$;

Print Snowflake Query in stored procedure

I am trying to use Snowflake stored procedures and would like to print the SQL statement in the stored procedure below to the screen.
CREATE OR REPLACE PROCEDURE read_western_provinces()
RETURNS VARCHAR NOT NULL
LANGUAGE JAVASCRIPT
AS
$$
var return_value = "";
try {
var command = "SELECT * FROM western_provinces ORDER BY province;"
var stmt = snowflake.createStatement( {sqlText: command } );
var rs = stmt.execute();
if (rs.next()) {
return_value += rs.getColumnValue(1);
return_value += ", " + rs.getColumnValue(2);
}
while (rs.next()) {
return_value += "\n";
return_value += rs.getColumnValue(1);
return_value += ", " + rs.getColumnValue(2);
}
}
catch (err) {
result = "Failed: Code: " + err.code + "\n State: " + err.state;
result += "\n Message: " + err.message;
result += "\nStack Trace:\n" + err.stackTraceTxt;
}
return return_value;
$$
;
How can I print the value of command variable (which contains the SQL) to the screen whenever stored procedure is executed?
thanks
I haven't found a way to do this, but there are a few options to get close at least.
You can insert output into a table.
You can return a variant instead with debugging output in an array or similar
return { "output":return_value, "debug":result }
Use a procedure to replicate something similar. See similar post from the snowflake community: https://community.snowflake.com/s/question/0D50Z00009Uu3cTSAR/debugging-procedures-technicques-print-std-out-etc)
Use getSqlText() to return a statement as text, see docs.
Add the return statement from below to the end of your procedure to have it print the statement when it is called.
CREATE OR REPLACE PROCEDURE read_western_provinces()
RETURNS VARCHAR NOT NULL
LANGUAGE JAVASCRIPT
AS
$$
var return_value = "";
try {
var command = "SELECT * FROM western_provinces ORDER BY province;"
var stmt = snowflake.createStatement( {sqlText: command } );
var rs = stmt.execute();
if (rs.next()) {
return_value += rs.getColumnValue(1);
return_value += ", " + rs.getColumnValue(2);
}
while (rs.next()) {
return_value += "\n";
return_value += rs.getColumnValue(1);
return_value += ", " + rs.getColumnValue(2);
}
}
catch (err) {
result = "Failed: Code: " + err.code + "\n State: " + err.state;
result += "\n Message: " + err.message;
result += "\nStack Trace:\n" + err.stackTraceTxt;
}
return stmt.getSqlText(); -- < will print/return the statement text
$$
;
If we use:
return { "output":return_value, "debug":result }
It gives an output like:
Just use call method after the procedure.
1.CALL read_western_provinces('database name','schema name');
Syntax
CALL ('database_name','schema_name');

Resources