What is the Snowflake equivalent code for While Exists (query)? - stored-procedures

I am trying to migrate a SQL Server Proc to Snowflake. In SQL Server, we have a proc which uses WHILE EXISTS and then Query. But I am unable to figure out the equivalent for Snowflake.
In SQL SERVER
WHILE EXISTS (QUERY)
BEGIN
---
END;
Snowflake Giving Error
WHILE EXISTS (QUERY) do
---
END WHILE;

The Snowflake equivalent is:
BEGIN
WHILE (EXISTS (SELECT * FROM tab)) DO
...
END WHILE;
END;
Output:
Sidenote:
The concept or running something in loop indicates the usage of batch processing like, removing/updating in chunks of X rows at a time to avoid long transaction/transaction log growth.
1:1 code translation may not be best approach when using Snowflake and it possible performing entire operation is single run instead.

Related

DB2: Procedure with a simple select return more than 15x slow compared to the same select in a query

I have a select that return a single column, using as where clause 4 columns, and I created a specific index for this query. When I do this select using Dbeaver, the result return in 30~50 milliseconds.
SELECT
column1
FROM
myTable
WHERE
column2 = a
AND column3 = b
AND (column4 = c AND column5 = d )
FOR READ ONLY WITH UR;
Now I created a procedure with this same simple select. The proc declare a P1, a 'cursor with return', do the select, open the cursor and close the P1. When I use the same dbeaver connection the result is returning between 1.2 ~ 1.6 seconds.
CREATE PROCEDURE myProc (
IN a DECIMAL(10),
IN b DECIMAL(10),
IN c DECIMAL(10),
IN d DECIMAL(10)
)
LANGUAGE SQL
DYNAMIC RESULT SETS 1
SPECIFIC myProc
P1: BEGIN
DECLARE cursor1 CURSOR WITH RETURN for
SELECT
column1
FROM
myTable
WHERE
column2 = a
AND column3 = b
AND (column4 = c AND column5 = d )
FOR READ ONLY WITH UR;
OPEN cursor1;
END P1
Is this huge return difference correct? If wrong, Is there something wrong in my procedure that justifies this return time difference? Or could be something wrong in the DB configuration or the server that justifies this difference, something like few resources in the DB server or something like the proc not using the index( I don't know if procs in the DB2 use the index by default like the queries )?
I am new in DB2 and new in procedures creation. Thank you in advance.
Best regards,
Luis
I don't know if is the best way, but I solved the problem using a solution that I read for SQL Server. The solution is create local variables that will receive the parameters values, and use the variable in the queries, to guarantee always the best execution plan. I didn't knew if this was valid to DB2, but my proc now has almost the same response time compared to query. Worked!
Link of SQL Server post: SQL Server: Query fast, but slow from procedure
In this link above a user called #Jake give this explanation:
"The reason this happens is because the procedures query plan is being cached, along with the parameters that were passed to it. On subsequent calls, this query plan generated will be reused with new parameters. This can cause problems because if the data is unevenly distributed, one parameter can generate a sub-optimal plan vs. another. Using local variables essentially does the same as OPTIMIZE FOR UNKNOWN because local variables cannot be sniffed."
I think that is the same for DB2, because worked. After I change these old procedures to use local variables my execution plan begun to use the indexes recently created

DB2 simple Select SP

i try to get an SP to run on DB2 connected with Squirrel
CREATE OR REPLACE PROCEDURE BOCA.TESTSP
(IN CASID INTEGER)
READS SQL DATA
DETERMINISTIC
LANGUAGE SQL
BEGIN
SELECT * FROM BOCA.TCASE C WHERE C.ID = CASID
END;
I get various errors based on where I put the ; (at end of statement etc)
i tried to follow this approach:
CREATE PROCEDURE [qualifier.]<procedure_name>
([IN | OUT | INOUT <argument_name> <datatype>,...])
{MODIFIES SQL DATA |
NO SQL |
CONTAINS SQL |
READS SQL DATA}
[[NOT] DETERMINISTIC]
LANGUAGE SQL
BEGIN [ATOMIC]
<procedure_body>
END
But did not succeed.
Anyone have a simple select that runs?
Stange is that an sample update I was able to create
Take some time to study the sample code that IBM supplies for SQL PL procedures, get these samples built and working in your environment. The samples are in the documentation, also they are on github, also they are in the SAMPLES directory of your Db2-server installation (for DB2 on Linux/Unix/Windows).
Your procedure has some mistakes:
missing statement separator after the SELECT statement
incorrect usage of SELECT in a routine. You either want to declare and open a cursor to return a result set to the caller or client, or you want to use SELECT...INTO to process the result of the query inside your routine.
missing valid separator at the end of the block of code (after the final END)
For SQuirrel SQL Client, before you connect to the database:
File > New Session Properties > SQL
(scroll down the list of properties until you see:
Statement Separator ;
Change the Statement Separator to #
Click OK.
Now connect to the database.
When you then type any SQL statement inside Squirrel (or a block, such as a trigger, stored-procedure, user defined function etc), you must now use the new statement separator instead of the previous default value at the end of the whole statement.
Inside of your routines , you will still need to use the semicolon to delimit statements inside the block, but remember to specify the new statement separator at the end of the block (after the final END in the stored procedure in your case).

DB2 Stored Procedure Not able to assign data to a variable

I have a simple stored procedure to calculate the sum of salaries of employees, sum of their squares and number of rows.
This is the stored procedure I have written:
I get an error in fetching the number of rows from the database and assigning it to a variable. What do I do? Using DB2 11.5
It helps to specify the exact error code when asking questions (don't write get an error, do write instead 'get error SQL0104N ...`.
Your mistake is that you have not followed the documented order for SQL statements in compound SQL blocks.
The SELECT statement can only appear after any cursor definitions, local procedures , and handlers if you have any.
So move the statement SELECT COUNT(*) INTO TOTAL_ROWS FROM EMPLOYEE; so that it appears after the DECLARE CURSOR1 ... line, the try to recompile.

tsql not firing (stored procedure via ssis) - SQL Server 2012

I've created one of many stored procedures as part of an ETL process and one of the queries within a stored procedure isn't executing.
The environment is SQL Server 2012 SP2.
The bizarre thing is this -
Run the select part of the insert (affected query) - returns rows
Run the insert (affected query) - inserts rows
Run the whole stored procedure via SSMS - inserts rows
Run via SSIS - all other queries run barring the one of concern!
There are no conditions in my stored procedure e.g. if x = True the Return and no debug code is in there either e.g. return. There are also no transactions and the table I am reading from is a staging table populated prveiously by a data flow.
The query:
INSERT INTO Person.CustomerLinks
(PersonID, SystemID, CustomerID_bin, CustomerActive)
SELECT i.PersonID
, s.SystemDefID
, i.CustomerID_bin
, 0
FROM Staging.IdentifyOutput i
JOIN Config.SystemDef s ON s.OutputType = i.OutputType
WHERE i.CustomerID_bin IS NOT NULL
AND i.OutputType IN ('L', 'X')
AND i.PersonID > 0
AND i.FileDuplicate = 1
AND i.PreferredRecord = 1
AND NOT EXISTS ( SELECT 1
FROM Person.CustomerLinks cl
WHERE cl.PersonID = i.PersonID
AND cl.CustomerID_bin = i.CustomerID_bin)
The procedure has a Try Catch block and the Catch will raise an error and no error is raised.
The only other non ETL code in the procedure is -
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
But I put this in all of my procedures in this application as I am not concerned about dirty reads as they won't happen.
I placed tsql directly after the insert to write to my audit system and ##RowCount was 0. Yet if I run the select now I get over 1.5 million rows back.
Any suggestions?
If you are using a Execute T-SQL task then please try replacing it with the Execute SQL Task.
I don't know what caused it, but I moved the specific SQL into another stored procedure and it worked. In reality, it warranted being in its own stored procedure by right as it was only semi related to the procedure in question.

How can I use call a stored procedure within SAS without using ProcSQL?

At my Co-Op my manager is asking me to take my SAS output tables that I've gathered and then to execute a stored procedure that will upload and update any data that has changed into an online KPI(Key Performance Indicators) excel sheet.
Apparently my boss isn't too sure of how to do this even and he's been programming for quite some time.
In laymen's terms this is what I need to do:
create a table of gathered KPI's (Done)
Send the table to the Stored Procedure (I don't want to use ProcSQL in SAS 9.3 because I would be hardcoding in too many fields)
Have the Stored procedure read into the online datasheet (done)
Replace KPI's if they have changed (done)
Here is the ProcSQL that I have figured: Ambiguous names have been given to keep anominity:
%let id = 'HorseRaddish';
%let pwd = 'ABC321';
proc sql;
connect to odbc (dsn='JerrySeinfeld' uid=&id pwd=&pwd);
execute (spKPIInsertUpdateKPIData '411', '7.2', '8808', 'M', 'NANANA', 'WorkStation', 'Testing1212', '1', '8/3/2013 10:42AM') by odbc;
disconnect from odbc;
quit;
run;
Above code works fine, but like I said it's a pain to hard code in KPI calues for hundreds of fields.
If it were me, and I had flexibility to do so, I would rewrite the SP to pull the parameters from a table and upload the table, then call the SP. That's got to be faster.
If it's not, you can script that SP line fairly easily. You will still run it in PROC SQL, but you don't have to write it out by hand.
Something like:
proc sql;
select cats("execute(spKPIInsertUdateKPIData '",var1,"''",var2,"','",var3,<... more ...>,"') by odbc") into :execlist separated by ';';
quit;
That creates a macro variable &execlist that contains the calls to the SP. Then you just do
proc sql;
connect to odbc ... ;
&execlist.
disconnect from odbc;
quit;
That does have some length limits, you might have to do it a bit differently (either cut it up or use %include) if you are over ~20k characters.
But again, this is probably not a very good way to do this - better is load to table and have the SP update from that table. Something like:
libname sqldb oledb init_string=whatever;
proc sql;
drop table sqldb._tempSP_KPI;
create table sqldb._tempSP_KPI as select * from <dataset containing values>;
connect to oledb (init_string=whatever);
<exec SP that uses the _tempSP_KPI table)>
quit;
quit;

Resources