Can a WHENEVER NOT FOUND Handler be used when there are no rows in a FOR loop?
I'm writing a template stored procedure generator as part of a 2E model transformation. I have thousands of 2E functions that I will need a stored procedure format and I'm trying to find the best and most efficient general case template for each type of 2E function.
This is my template proceedure
CREATE PROCEDURE SP_M3_000TSG (
IN HONB DECIMAL(9, 0)
, OUT ABCD CHAR(3) DEFAULT ' '
, OUT EECD CHAR(6) DEFAULT ' '
, OUT RTN CHAR(7) DEFAULT NULL
)
LANGUAGE SQL
PROGRAM TYPE SUB
-- #######################################################################
-- # SP_M3_000TSG
-- #######################################################################
BEGIN
DECLARE SQLCODE INTEGER DEFAULT 0;
DECLARE SQLSTATE CHAR(5) DEFAULT '00000';
M3_INIT:BEGIN
-- do some init stuff
END M3_INIT;
FOR M3_000TSG
**declare WHENEVER NOT FOUND **
AS CUR_ECDQREL1 CURSOR
FOR
SELECT * FROM ECDQREL1 WHERE DQHONB = HONB
DO
do some stuff;
END FOR;
GO TO M3_EXIT;
M3_NO_ROWS: BEGIN
do some stuff for no rows;
END M3_NO_ROWS;
M3_EXIT: BEGIN
do some stuff;
RETURN;
END M3_EXIT;
END
With current versions of Db2, you cannot use WHENEVER NOT FOUND syntax inside SQL-PL procedures.
Instead, you can use this syntax only in embedded-SQL programs where the pre-compiler acts on it.
In SQL-PL procedures, you can either declare a handler for NOT FOUND, or you can code checks for SQLCODE 100 or SQLSTATE '02000' .
Related
Is it possible to have default values in arguments of Stored procedures of Snowflake. For the below example, I am getting error. Please help
syntax error line 1 at position 53 unexpected ''test''.
create or replace procedure test(arg1 string default 'test')
returns string not null
language sql
as
$$
begin
return arg1;
end;
$$
;
Snowflake's procedures applies polymorphism instead of using default value. This solution is when you do not want to call sp like func1(Null)
For example (sql scripting):
create or replace procedure func1(arg1 varchar, arg2 varchar)
...
create or replace procedure func1(arg1 varchar)
...
call func1(arg1 , 'some-default-value')
...
One option could be providing NULL as value and handle it at the begining of the stored procedure with COALSESCE:
create or replace procedure test(arg1 string)
returns string not null
language sql
as
$$
begin
arg1 := COALESCE(arg1, 'test');
return arg1;
end;
$$;
CALL test(NULL);
-- test
Setting a default value/values as arguments directly in Stored procedures is not available in Snowflake currently
The below link can be referred for the allowed syntax in Stored Procedures
https://docs.snowflake.com/en/sql-reference/sql/create-procedure.html#syntax
I've seen in the help guides that you cannot use a call statement in a teradata dynamic sql statement without output parameter.
I assume this implies I can, If the proc has an output parameter.
has anyone done this?
Scenario -
I have a table that at some point I'll expand out in terms of fields for logic on when things should run, and this table is managed elsewhere -
CREATE TABLE DB.SP_Test
(
ProcName VARCHAR(250)
,ProcRun VARCHAR(1)
);
now I added chrTest as an output however, I am still getting an error on run (no compile error)
The error :-
SQL_State SQL_Exception
T7689 Invalid dynamic SQL statement.
REPLACE PROCEDURE DB.Test_Control (OUT chrTest VARCHAR(250) )
SQL SECURITY INVOKER
LMain:
BEGIN
DECLARE sqlProcRun VARCHAR(20000);
DECLARE CONTINUE HANDLER
FOR SqlException
BEGIN
-----------------------------------------------------------------------------
DECLARE strExceptionText VARCHAR(250);
GET DIAGNOSTICS EXCEPTION 1 strExceptionText = Message_Text;
INSERT INTO DB.PROC_ERROR VALUES
(
'Test_Control'
,:SqlState
,strExceptionText
,Current_Timestamp
)
;
END;
-----------------------------------------------------------------------------
SET sqlProcRun ='';
L0:
FOR procs_run_cursor AS select_list
CURSOR FOR
SELECT Trim(ProcName) AS ProcName
FROM DB.SP_Test
DO
/*creating a lost of call statements to run*/
SET sqlProcRun = sqlProcRun ||'CALL DB.'||procs_run_cursor.ProcName|| '();';
END FOR L0;
EXECUTE IMMEDIATE sqlProcRun;
END;
Enviroment:
DB2 Version 11.1,
OS - Linux
How to get the result table of stored procedure into a temp table?
The table and the result have the same table configuration (firstColumn int, secondColumn nvarchar(255))
I'm assuming your stored procedure returns an open cursor, so you want to consume that cursor, inserting its contents into a session table (declared global temporary table) on Db2-LUW.
In addition to fetch and insert statements, you need to understand the following statements:
associate result set locator ... with procedure ...
allocate ... cursor for result set ...
Here is a deliberately artificial example of a nested stored procedure, which shows fetching a result-set from a nested procedure into a session table. The purpose is to show how the syntax works, rather than to do anything useful with data (as the net effect can be equally met by a simple catalog query in this case). This example can be run at the Db2 command-line (for example at the bash shell, after you connected to a database with appropriate permissions):
update command options using s on ;
--#SET TERMINATOR #
create or replace procedure alltabs
dynamic result sets 1
language sql
specific alltabs
begin
declare v_cur cursor with return to caller for select tabschema,tabname,type from syscat.tables ;
open v_cur;
end#
declare global temporary table session.thetables(tabschema varchar(128), tabname varchar(128))
not logged with replace on commit preserve rows #
create or replace procedure populate_dgtt()
language sql
specific populate_dgtt
begin
declare v_rs result_set_locator varying;
declare v_tabschema varchar(128);
declare v_tabname varchar(128);
declare v_type char(1);
declare sqlstate char(5) default '00000';
call alltabs;
associate result set locator (v_rs) with procedure alltabs;
allocate v_rscur cursor for result set v_rs;
fetch from v_rscur into v_tabschema, v_tabname, v_type;
while ( sqlstate = '00000') do
if v_type='V' and v_tabschema='SYSSTAT'
then
insert into session.thetables(tabschema,tabname) values (v_tabschema, v_tabname);
end if;
fetch from v_rscur into v_tabschema, v_tabname, v_type;
end while;
return;
end#
call populate_dgtt()#
select rtrim(Tabschema)||'.'||rtrim(tabname) from session.thetables #
I have a Sql File named procedure.sql with a procedure.
Maria DB Version: Server version: 10.0.29-MariaDB-0ubuntu0.16.04.1 Ubuntu 16.04
But I am getting ERROR AS Follows:
>mysql -u root -p XXX < /home/azure/Downloads/procedure.sql
>Enter password:
>ERROR 1064 (42000) at line 2: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '();
>USE XXX;
>CREATE OR REPLACE PROCEDURE XXX.updateDoc_StorageID ()
>BEGIN' at line 1
Can anyone help me please?
procedure.sql Code:
DELIMITER //
DROP PROCEDURE IF EXISTS XXX.updateDoc_StorageID;
USE XXX;
CREATE OR REPLACE PROCEDURE XXX.updateDoc_StorageID ()
BEGIN
DECLARE myTransacID INT DEFAULT 0;
DECLARE myTransProductId INT DEFAULT 0;
DECLARE myDocStoreID VARCHAR(500) DEFAULT '0';
DECLARE my_count INT DEFAULT 0;
DECLARE trans_csr CURSOR FOR SELECT 1,2 FROM MainTable ORDER BY TransactionID;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET my_count=1;
SET my_count=0;
OPEN trans_csr;
trans_loop:LOOP
FETCH trans_csr INTO myTransacID,myTransProductId;
IF my_count=1 THEN
LEAVE trans_loop;
END IF;
If(myTransProductId=8)
then
if exists(....)
then
.......
end if;
elseif (myTransProductId=11)
then
if exists(........)
then
.......
END IF;
END IF;
END LOOP trans_loop;
CLOSE trans_csr;
SET my_count=0;
END;
//
DELIMITER ;
The Reference I got is from :
https://mariadb.com/kb/en/mariadb/create-procedure/
The syntax error is not for CREATE PROCEDURE, it's for the preceding DROP PROCEDURE, you shouldn't have brackets there.
DROP PROCEDURE IF EXISTS XXX.updateDoc_StorageID;
The second error follows, since the procedure hasn't been dropped, it still exists.
Also, fix the delimiters -- if you set $$ at the start, then every further query should end with $$, not with semicolon.
The right syntax for version 10.0.x StoredProcedure will be:
DELIMITER //
DROP PROCEDURE IF EXISTS XXX.updateDoc_StorageID;
USE XXX;
CREATE OR REPLACE PROCEDURE XXX.updateDoc_StorageID ()
BEGIN
DECLARE myTransacID INT DEFAULT 0;
DECLARE myTransProductId INT DEFAULT 0;
DECLARE myDocStoreID VARCHAR(500) DEFAULT '0';
DECLARE my_count INT DEFAULT 0;
DECLARE trans_csr CURSOR FOR SELECT 1,2 FROM MainTable ORDER BY TransactionID;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET my_count=1;
SET my_count=0;
OPEN trans_csr;
trans_loop:LOOP
FETCH trans_csr INTO myTransacID,myTransProductId;
IF my_count=1 THEN
LEAVE trans_loop;
END IF;
If(myTransProductId=8)
then
if exists(....)
then
.......
end if;
elseif (myTransProductId=11)
then
if exists(........)
then
.......
END IF;
END IF;
END LOOP trans_loop;
CLOSE trans_csr;
SET my_count=0;
END;
//
DELIMITER ;
I have a db2 stored proc which contains a select query. I want to abort or fail this stored proc if the select query is returning any value. Please help.
SET CURRENT SCHEMA = abc;
SET CURRENT PATH = abc,pqr;
CREATE OR REPLACE PROCEDURE abc.VALID_xyz ( )
SPECIFIC SQL150421070712734
LANGUAGE SQL
NOT DETERMINISTIC
EXTERNAL ACTION
MODIFIES SQL DATA
CALLED ON NULL INPUT
INHERIT SPECIAL REGISTERS
OLD SAVEPOINT LEVEL
begin
DECLARE C1 CURSOR WITH RETURN
FOR select * from xy_table;
open C1;
RETURN;
END;
SET CURRENT SCHEMA = abc;
If xy_table has any rows , I need to fail this stored proc.
The SIGNALcommand can trigger a predefined or custom SQLSTATE that will abort the current SQL procedure (or atomic block of SQL statements) as if an actual error had occurred.
SET CURRENT SCHEMA = abc;
SET CURRENT PATH = abc,pqr;
--#SET TERMINATOR #
CREATE OR REPLACE PROCEDURE abc.valid_xyz()
SPECIFIC valid_xyz
NO EXTERNAL ACTION
LANGUAGE SQL
BEGIN
IF EXISTS ( SELECT 1 FROM xy_table FETCH FIRST ROW ONLY )
THEN
SIGNAL SQLSTATE '75002'
SET MESSAGE_TEXT =
'Table XY_TABLE contained data when it was expected to be empty.';
END IF;
END#
--#SET TERMINATOR ;
CALL valid_xyz();
SQL0438N Application raised error or warning with diagnostic text:
"Table XY_TABLE contained data when it was expected to be empty.". SQLSTATE=75002