How to apply line break in the comment for snowflake procedures? - snowflake-cloud-data-platform

Trying to input line break in the comment section, but it failed to display row by row.
Examples: When execute the query below, the output of the comment should be followed by the format below. However, the comment becomes "FunctionName:IfElse\nDescription: ..........."
CREATE OR REPLACE PROCEDURE APPROVALS_J_TEST("MYSTR" VARCHAR(16777216))
RETURNS VARCHAR(16777216)
LANGUAGE JAVASCRIPT
**comment** = FunctionName: IfElse
Description: ...........
EXECUTE AS OWNER
AS
'if (MYSTR == ''0001'')
{
return ''Success''
}
else if (MYSTR == ''0002'')
{
return ''Success''
}
else {
return ''Failure''
}
';

The CREATE PROCEDURE docs note comment is a single quote wrapped string.
COMMENT = '<string_literal>'
so lets try one of those:
CREATE OR REPLACE PROCEDURE APPROVALS_J_TEST("MYSTR" text)
RETURNS text
LANGUAGE JAVASCRIPT
comment = 'FunctionName: IfElse
Description: ...........
'
EXECUTE AS OWNER
AS
'
if (MYSTR == ''0001'')
{
return ''Success''
}
else if (MYSTR == ''0002'')
{
return ''Success''
}
else {
return ''Failure''
}
';
show procedures;
So it seems to work

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

Is it possible to get both the RAISEERROR message and the return value from a stored procedure in .NET?

I have this procedure that does a RAISEERROR and a return #tmp_cnt at the end. This RAISEERROR doesn't stop the procedure from executing as it should return the tmp_cnt as well. I use this in .NET and my code goes into the catch (SqlException e) part so this tmp_cnt doesn't get returned. This is the code for it
(string, int) result;
result.Item1 = null;
result.Item2 = -1;
try {
result.Item2 = await _context.Database.ExecuteSqlRawAsync("EXECUTE core.STORED_PROCEDURE", params);
} catch (SqlException e) {
foreach(SqlError error in e.Errors) {
if (error.Class > 10) {
result.Item1 = error.Message;
}
}
}
This way, I only get the error.Message while the result.Item2 remains -1 and I'm aware that this is a normal thing to do as this is what it should do. If I remove the try/catch part, the app throws an exception and code 500. The question I have is, is there a way to get both the RAISEERROR and the return from a stored procedure in .NET? This is the SQL part
IF #tmp_cnt < #ent_cnt
BEGIN
DECLARE #msg AS NVARCHAR(MAX) = CONCAT('Not all of the selected entities are eligible for change. Will be changed for ',
CAST(#tmp_cnt AS NVARCHAR(50)), ' out of the selected ', CAST(#ent_cnt AS NVARCHAR(50)), ' entities.')
RAISERROR(#msg, 15, 1)
RETURN #tmp_cnt;
END
If not possible, have you ever stumbled upon a scenario like this and is there a workaround for it?

get the value and use that value as check to process next steps in snowflake

I have to check the distinct "Status" columnin 1 table and and if that Status='Complete' then I have to call different other Stored Procedures. How can I retrieve the value from the sample code below.
CREATE OR REPLACE PROCEDURE TEMP_KK()
RETURNS STRING NOT NULL
LANGUAGE JAVASCRIPT
AS
$$
var load_status=`SELECT DISTINCT TABLESTATUS from "PLNG_ANALYSIS"."LOAD"."LET_LOAD_VERIFICATION";`
var load_check = snowflake.execute({sqlText: load_status});
if (load_check='Complete') /* HOW DO i get the TABLESTATUS value returned from above select statement */
{
CALL ABC();
CALL XYZ();
}
$$;
CALL TEMP_KK();
Assuming that query returns single row:
var load_status=`SELECT DISTINCT TABLESTATUS from "PLNG_ANALYSIS"."LOAD"."LET_LOAD_VERIFICATION";`
var load_check = snowflake.execute({sqlText: load_status});
load_check.next();
if(load_check.getColumnValue(1) == 'Complete') {
...
}

How to find Length of characters in MS SQL Server 2008 excluding the length of column name being given?

Consider below example:
Declare #Email varchar(90) = 'aaa#abcdefghighijklmnopqrstufdghfhfhfhgggfhfghgfbdfghhgdfhffdgfdgdsdfgfdgfdgdfgfdgdfgdfgdfffsdgffgdfgvwxyzsderkslwotsneiwnsyr.com'
IF(len(#Email) > 89)
Select 'Length of Email should not be greater than 90 - Error Message'
else
Select 'Correct email'
It works fine. However, when I implement the same logic in Stored Procedure. It doesn't work.
Note: #Email is simply declare. I have Email column in one of my table, say, "BulkImport" with datatype varchar(90). User can input incorrect format, length can be anything.
Hence, I want to find out its length if > 90 and validate it from sql.
Actual Code in Stored Procedure which doesn't work and throws and error 'Received an invalid column length from the bcp client for colid...' is given below:
Select
ISNULL(BI.Email, '') ColumnName,
'Length of Email sholud not be greater than 90'
From
BulkImport BI
Where
ISNULL(LEN(BI.Email), '') > 89
"I am well aware that, since Length of column "Email" is varchar(90), I am getting internal error However, I want to replace internal error with validation, which any user can understand."
Any solution to these or any substitute to LEN function in SQL will be more helpful.
Here's my code
public void UpdateBulkImportTable(Process process, eType objectType, DataTable sourceTable)
{
bool _releaseProcess = false;
if (process == null)
{
process = DataAccessManager.NewProcess(); _releaseProcess = true;
}
else process.ClearParameters();
try
{
if(_releaseProcess) process.BeginTransaction();
process.UpdateBulkData(objectType, sourceTable);
if (_releaseProcess) process.CommitTransaction();
}
catch (Exception ex)
{
if (process != null && _releaseProcess) process.RollbackTransaction();
throw new ValidationException(ex.Message);
}
finally
{
if (process != null && _releaseProcess) process.Release();
}
}
Does it work if you change the last line into from
Where
ISNULL(LEN(BI.Email), '') > 89
into
Where
LEN(ISNULL(BI.Email, '')) > 89

Oracle Pro*C : Handling end of fetch cursor

I can't figure out the problem on my code :
/* Declare a cursor for the FETCH statement. */
EXEC SQL DECLARE customer_cursor CURSOR FOR
SELECT CUSTOMER_ID, CUSTOMER_NAME
FROM CUSTOMER_TABLE
WHERE CUSTOMER_CARD_NUM = :argv[1];
if ( sqlca.sqlcode != 0 )
{
printf("Declare cursor failed\n");
return( sqlca.sqlcode );
}
EXEC SQL OPEN customer_cursor;
if ( sqlca.sqlcode != 0 )
{
printf("Open cursor failed\n");
return( sqlca.sqlcode );
}
EXEC SQL WHENEVER NOT FOUND GOTO no_match;
for ( ;; )
{
/* Fetching data */
EXEC SQL FETCH customer_cursor
INTO :var_customer_id, :var_customer_name;
if ( sqlca.sqlcode != 0 )
{
EXEC SQL CLOSE cust_data_cursor;
return ( sqlca.sqlcode );
}
/* Doing some stuff here */
processing_customer();
}
EXEC SQL CLOSE customer_cursor;
/* Handling the no data found here */
no_match:
printf("NO CUSTOMER MATCHING THIS CARD_NUM\n");
/* Some stuff */
......
return 1;
My query is supposed to return just one row or nothing, when nothing is returned all is ok, but when ther's a matching, the function processing_customer is executed and the strange is that the no_match is executed too.
Thanks for helping me to fix that.
As #Roger Cornejo suggests, you need a way to not execute the 'no match' section if there is a match. no_match: is just a label so there's nothing to tell your code not to execute that section. You either need to return before that label, or goto something after it. You also need to close the cursor in the no-match scenario.
But this seems unnecessarily messy and as #Arion hinted you don't need an explicit cursor for this - just do a select into and catch the exception.
EXEC SQL SELECT CUSTOMER_ID, CUSTOMER_NAME
INTO :var_customer_id, :var_customer_name
FROM CUSTOMER_TABLE
WHERE CUSTOMER_CARD_NUM = :argv[1];
if (sqlca.sqlcode == 1403)
{
printf("NO CUSTOMER MATCHING THIS CARD_NUM\n");
/* Some stuff */
......
return 1;
}
if (sqlca.sqlcode != 0)
{
return ( sqlca.sqlcode );
}
/* Doing some stuff here */
processing_customer();
You've said there will be zero or one rows; if there are more than one you'll get a too-many-rows error (ORA-02112).
add GOTO after "EXEC SQL CLOSE customer_cursor;"
Change your label "no_match" to "no_more_records" and you'll realize why it runs 2 times:
a) when there are no records, the FETCH raises the NOT FOUND condition inmediatly and therefore will go to the label "no_more_records"
b) when there is one (or more) record(s), the FETCH is executed returning the first record.
Then the
if ( sqlca.sqlcode != 0 )
evaluates to false (in fact, only useful to trap other problems) and then
processing_customer();
After it, the FETCH run again (by the infinity for) and behave as in (a): no_more_records condition arrives.

Resources