Snowflake proc issue - snowflake-cloud-data-platform

I am having issue while executing below proc in snowflake.
Here is the code.
"**
create or replace procedure test_0916() returns string not null language javascript execute as owner as $$ try {
var sqlquery=" ";
var outcome=" ";
var x=" ";`
sql_command =select salary from EMPLOYEES where employee_id=8`;
var rs=snowflake.execute({sqlText:sql_command});
rs.next();/* Here not using while loop because it returns only one value*/
x=rs.getcolumnValue(1);
sqlquery=fltConvUomPK; }
catch (err) {
return "Error: " + err;
}"
return sqlquery;
$$;
**"
When I am trying to execute the proc as below
Blockquote
call test_0916();
I am getting below error.
Error: TypeError: rs.getcolumnValue is not a function

The method name is getColumnValue()
Can you check the spelling?
https://docs.snowflake.com/en/sql-reference/stored-procedures-api.html#getColumnValue

Related

Snowflake Stored Procedure For Loop

i'm working with Snowflake,
i created this Stored Procedure, it's purpose is to do the following steps:
extract the relevant 'application_id' values from the SQL query
use a FOR loop over a SQL query, with the 'application_id' values that i extracted
in step 1, and delete the relevant rows from the target table.
when i call the Stored Procedure, it runs without errors, but it doesn't do anything ( the relevant records are not been deleted).
i added my SP code,
please let me know if you see any syntax / logic errors,
thanks
CREATE OR REPLACE PROCEDURE DWH.sp_testing()
RETURNS string
LANGUAGE javascript
strict
EXECUTE AS owner
AS
$$
try
{
var application_list = ` SELECT application_id
FROM PUBLIC.my_source_table_name
WHERE my_flag = 1
`
var query_statement = snowflake.createStatement({sqlText: application_list});
var application_list_result = query_statement.execute();
for (i = 1; i <= query_statement.getRowCount(); i++)
{
application_list_result.next()
application_id = application_list_result.getColumnValue(1)
var delete_daily_records = `
DELETE FROM PUBLIC.my_target_table_name AS target
WHERE target.application_id = ${application_id}
`
snowflake.execute({sqlText: delete_daily_records});
}
}
catch (err)
{
throw "Failed: " + err;
}
$$
;
CALL DWH.sp_testing();
Are you sure your query is returning data? Also are you sure the target table has data matching your DELETE statement?
The following test works for me using your stored procedure:
select count(*) from citibike_trips where end_station_id=6215;
returns: 14565
Now, I created your stored proc:
CREATE OR REPLACE PROCEDURE sp_testing()
RETURNS string
LANGUAGE javascript
strict
EXECUTE AS owner
AS
$$
try
{
var application_list = `SELECT end_station_id
FROM citibike_trips
WHERE end_station_id=6215 limit 10
`
var query_statement = snowflake.createStatement({sqlText: application_list});
var application_list_result = query_statement.execute();
for (i = 1; i <= query_statement.getRowCount(); i++)
{
application_list_result.next()
end_station_id = application_list_result.getColumnValue(1)
var delete_daily_records = `
DELETE FROM citibike_trips AS target
WHERE target.end_station_id = ${end_station_id}
`
snowflake.execute({sqlText: delete_daily_records});
}
}
catch (err)
{
throw "Failed: " + err;
}
$$
;
Run it:
CALL SP_TESTING();
Shows NULL as result (expected since it is not returning anything).
But then when I check the table again:
select count(*) from citibike_trips where end_station_id=6215;
returns: 0

Unable to execute multiple stored procedures in the parent stored procedure Snowflake

Iam new to Snowflake so this question might be very silly but iam unable to resolve this issue,
I have 2 child procs child1 and Child2 which are called from a Parent procedure, the issue is only one child proc is getting executed, whichever is called first and skips the other procedure.
create or replace procedure parent_prc(P_SRC_DB varchar,P_TGT_DB varchar)
returns varchar
language javascript
as
$$
var some_sql_cmd = "TRUNCATE TABLE "+P_SRC_DB+".schema_a.table1"
var some_sql_stmt = snowflake.createStatement( {sqlText: trunc_prestg_cmd} );
var child1_proc_exec_cmd = "call
"+P_TGT_DB+".schema_a.child1_proc('"+P_SRC_DB+"','"+P_TGT_DB+"')"
var child1_proc_stmt = snowflake.createStatement( {sqlText: child1_proc_exec_cmd} )
var child2_proc_exec_cmd = "call
"+P_TGT_DB+".schema_a.child2_proc('"+P_SRC_DB+"','"+P_TGT_DB+"')"
var child2_proc_stmt = snowflake.createStatement( {sqlText: child2_proc_exec_cmd} )
try
{
child1_proc_stmt.execute();
}
catch(err)
{
return(" Error :"+err);
}
try
{
child2_proc_stmt.execute();
}
catch(err)
{
return(" Error :"+err);
}
try
{
some_sql_stmt.execute();
}
catch(err)
{
return("Truncate Error :"+err);
}
$$
It executes Child1_proc and directly goes some_sql_stmt execution and Child2_proc is not executed, if i remove child1_proc, the Child2_proc is executed, iam not sure what is the issue, please help..
Can you confirm that the child1_proc is successful? You should also see an error in the parent_prc call. If you look in query history for the session id (use: select current_session(); to get session id), you can see all queries executed by the stored procedure and it should help identify the issue.
In the example provided above, the below part will have a syntax error, but this wouldn't allow the procedure to compile. (some_sql_cmd should be trunc_prestg_cmd)
var some_sql_cmd = "TRUNCATE TABLE "+P_SRC_DB+".schema_a.table1"
var some_sql_stmt = snowflake.createStatement( {sqlText: trunc_prestg_cmd}
);

I am trying Try and Catch Error handling for snowflake stored procedure. in the Stored procedure there are four different statements s

I am trying to do error handling for snowflake stored procedure. The stored procedure has 4 SQL statement inside. I need check errors for all for statement. When error pops, i need to know which Statement error. How to achieve this? Thanks in advance. I appreciate it.
CREATE OR REPLACE PROCEDURE dw.sp_fidctp_audit_trail_load(SYSDATE varchar)
RETURNS STRING
LANGUAGE javascript
AS
'
var sql_command = "truncate table STG.tb_fidctp_audit_trail_input";
var result = snowflake.execute ( {sqlText: sql_command, binds: [SYSDATE]});
sql_command =`COPY INTO STG.tb_fidctp_audit_trail_input (record_id,ORDER_ID,PARENT_ORDER_ID,EVENT_TYPE,EVENT_DATETIME,PRIMARY_STATE,SECONDARY_STATE,CURRENT_SERVICE_ID,CURRENT_EXECUTOR_ID,TRADING_QUANTITY,LIMIT_PRICE,EVENT_TEXT,ORDER_NOTES,REASON_TEXT,ROUTED_ORDER_CODE,ROOT_ORDER_ID,INSTRUMENT_CODE,ORDER_SOURCE,LEAVES,ACCT_ID,CUST_CROSS_ID,ORDER_FLAGS)
from #STG.CTP_STAGE/AUDIT_TRAIL.TOP.`;
sql_command += SYSDATE;
sql_command += ".psv.gz file_format = (FORMAT_NAME = ''STG.CTP_AUDIT_TRAIL_FF'', ERROR_ON_COLUMN_COUNT_MISMATCH = TRUE, encoding = ''iso-8859-1'') ";
try{
result = snowflake.execute (
{sqlText: sql_command, binds: [SYSDATE]}
);
return "Succeeded."; // Return a success/error indicator.
}
catch (err) {
return "Failed: " + err + "ERROR ON COPY STATEMENT"; // Return a success/error indicator.
}
sql_command = `delete from DW.tb_fidctp_audit_trail
where SYSDATE = to_date((:1), ''YYYYMMDD'')`;
result = snowflake.execute ( {sqlText: sql_command, binds: [SYSDATE]});
sql_command = ` insert into DW.tb_fidctp_audit_trail(sysdate, order_id, parent_order_id, root_order_id, event_datetime, instrument_code, event_text,reason_text, current_service_id, current_executor_id, trading_quantity, leaves )
select to_date(left(event_datetime, 8), ''YYYYMMDD''), order_id, parent_order_id, root_order_id, to_timestamp(left(event_datetime, 24), ''YYYYMMDD HH24:MI:SS.FF''), instrument_code, event_text, reason_text, current_service_id, current_executor_id, cast(trading_quantity as NUMBER(18,0)), cast(leaves as NUMBER(18,0))
from STG.tb_fidctp_audit_trail_input
`;
try{
snowflake.execute (
{sqlText: sql_command, binds: [SYSDATE]}
);
return "Succeeded."; // Return a success/error indicator.
}
catch (err) {
return "Failed: " + err + "ERROR ON INSERT STATEMENT"; // Return a success/error indicator.
}
'
;
There are a few things to do here. Let's start with the create header:
CREATE OR REPLACE PROCEDURE dw.sp_fidctp_audit_trail_load(SYSDATE varchar)
RETURNS STRING
LANGUAGE javascript
AS
'
When you use a single quote to enclose the body of a JavaScript procedure, it makes using single quotes in SQL statements inside the body very cumbersome, having to double the single quotes. To avoid that, you can use an alternate string terminator in Snowflake, $$ like this:
CREATE OR REPLACE PROCEDURE dw.sp_fidctp_audit_trail_load(SYSDATE varchar)
RETURNS STRING
LANGUAGE javascript
AS
$$
// Body goes here. There's no longer a need to escape single quotes
$$;
The issue with the return values is in this part:
return "Succeeded."; // Return a success/error indicator.
}
catch (err) {
return "Failed: " + err + "ERROR ON COPY STATEMENT"; // Return a success/error indicator.
}
In JavaScript, when the return statement is used in the main function, it leaves the main function, which terminates the stored procedure. This means if the copy statement succeeds, the procedure will exit and return "Succeeded." If the copy statement fails, it will hit a different return statement and exit with the error message.
Either way, it will terminate execution after that code block.
Take the return statements out of the successful branches of the try/catch blocks except for the last one.
You can just print the statement in the CATCH statement, either by printing the sql_command variable, or using getSqlText() function from the Statement object.
CREATE OR REPLACE PROCEDURE test_catch_error_sp(SYSDATE varchar)
RETURNS STRING
LANGUAGE javascript
AS
$$
var commands = [];
var params = [];
var results = {"success": [], "failed": []};
commands[0] = "create or replace table test1 (a int)";
params[0] = [];
commands[1] = "INSERT INTO test1 values (?)";
params[1] = [SYSDATE];
commands[2] = "drop table test1";
params[2] = [];
var stmt = null;
for (i = 0; i < commands.length; i++) {
try {
stmt = snowflake.createStatement({sqlText: commands[i], binds: params[i]});
var result = stmt.execute();
results['success'].push(stmt.getSqlText());
stmt = null; // reset it
} catch (err) {
// if createStatement failed, then stmt will still be null
results['failed'].push(
"Failed: " + err + ". ERROR ON STATEMENT: '" + stmt ? stmt.getSqlText() : commands[i] + "'"
);
}
}
return JSON.stringify(results);
$$
;
call test_catch_error_sp('2020-01-01');
-- returns:
-- {"success":["create or replace table test1 (a int)","drop table test1"],"failed":["INSERT INTO test1 values (?)"]}

Logging a procedure information into a table in snowflake

I have a table that logs certain information about procedures that are called
PROCEDURE_NAME, PARAMETERS_PASSED, START_TIME,END_TIME, ERROR_MESSAGE ... and others
I am creating a procedure which inserts into this table the information I want.
However, I do not know how I am to pass the error message from the stored procedure that is called
into my new procedure
Is there a way to save this error message
EX)
SP1 - STARTS
SP1 - ENDS & THERE IS AN ERROR
LOG_STORED_PROCEDURE(SP1_NAME,SP1_PARAMETERS,SP1_START_TIME,SP1_END_TIME,ERROR_MESSAGE)
Use JavaScript's try/catch block and do the insert into an error table in the catch block. Here's a sample you can modify:
create or replace procedure catch_error_example()
returns string
language javascript
execute as caller
as
$$
// Try to insert into a non-existent table.
try{
cmd = {sqlText: "insert into NON_EXISTENT_TABLE select 1"};
stmt = snowflake.createStatement(cmd);
stmt.execute();
} catch (e) {
cmd = {sqlText: `insert into ERROR_LOG (STORED_PROC, ERROR_MESSAGE) values ('CATCH_ERROR_EXAMPLE', '${escapeString(e.message)}')`};
stmt = snowflake.createStatement(cmd);
stmt.execute();
}
return "Check error log.";
function escapeString(value) {
var s = value.replace(/\\/g, "\\\\");
s = s.replace(/'/g, "''" );
s = s.replace(/"/g, '\\"');
s = s.replace(/\s+/g, " ");
return s;
}
$$;
create temp table ERROR_LOG(ERROR_TIME timestamp default current_timestamp, STORED_PROC string, ERROR_MESSAGE string);
call catch_error_example();
select * from ERROR_LOG;

Snowflake JS Proc

create or replace procedure test_09172(c_custkey varchar(25)
,c_mktsegment varchar(25)
,cname varchar(25)) returns string not null language javascript execute as owner as $$
var sqlquery="";
var fltConvUomPK="";
var fltConvFactorPK="";
var ParentClass="";
var VMAJOR="";
var VMINOR="";
try {
var sql_command =`SELECT C_ADDRESS,C_NATIONKEY
from customers
WHERE c_custkey=C_CUSTKEY and c_name=CNAME and C_MKTSEGMENT=C_MKTSEGMENT`;
var rs=snowflake.createStatement( {sqlText: sql_command});
var result_set1 = rs.execute();
}
catch(err)
{
return err.message
}
return rs.getSqlText(); $$;
While executing "call test_09172('537289','FURNITURE','Customer#000537289');"
I am getting below error.
JavaScript execution error: Uncaught TypeError: Cannot read property
'getSqlText' of undefined in TEST_09172 at ' return rs.getSqlText();'
position 14 stackstrace: TEST_09172 line: 28
Please help me on this to fix
The error seems related to an undefined object, but your code worked without any errors when I tried to reproduce it.
I noticed that you do not bind your parameters to your SQL:
var sql_command =`SELECT C_ADDRESS,C_NATIONKEY
from customers
WHERE c_custkey=C_CUSTKEY and c_name=CNAME and C_MKTSEGMENT=C_MKTSEGMENT`;
SQL is not case-sensitive, so you just compare the columns with themselves (c_custkey=C_CUSTKEY and C_MKTSEGMENT=C_MKTSEGMENT). c_name=CNAME will probably produce an error.
To avoid confusion between the column and parameter names, I rewrote the query:
create or replace procedure test_09172(c_custkey_p varchar(25)
,c_mktsegment_p varchar(25)
,c_name_p varchar(25)) returns string not null language javascript execute as owner as $$
var sqlquery="";
var fltConvUomPK="";
var fltConvFactorPK="";
var ParentClass="";
var VMAJOR="";
var VMINOR="";
try {
var sql_command =`SELECT C_ADDRESS,C_NATIONKEY
from customers
WHERE c_custkey=? and c_name=? and C_MKTSEGMENT=?`;
var rs=snowflake.createStatement( {sqlText: sql_command , binds:[ C_CUSTKEY_P, C_NAME_P , C_MKTSEGMENT_P ] });
}
catch(err)
{
return err.message
}
return rs.getSqlText();
$$;
On my tests, it works as expected but I don't have your data so you should test it.
The method getSqlText is available for the Statement object not ResultSet, see here:
getSqlText()
This method returns the text of the prepared query in the Statement object.

Resources