Dynamic SQL calling another stored procedure in Teradata - stored-procedures

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;

Related

HSQL problem when using TIMESTAMP value as IN parameter in stored procedure

Overview HSQL IN parameter of type TIMESTAMP doesn't work as expected for HSQL stored procedure.
Given the following DDL :
CREATE TABLE TS_STORE (
ID_COL VARCHAR(20) NOT NULL PRIMARY KEY,
TS TIMESTAMP
);
A DML statement such as :
INSERT INTO TS_STORE (ID_COL, TS) VALUES ('key1', '2020-02-19 12:17:53');
will successfully insert a row.
Then when I attempt to create a stored procedure to do the same as:
CREATE PROCEDURE TEST_PROC(IN IN_KEY VARCHAR(20), IN IN_TS TIMESTAMP)
MODIFIES SQL DATA
BEGIN ATOMIC
INSERT INTO TS_STORE(ID_COL, TS)
VALUES (IN_KEY, IN_TS);
END;
and attempt to call it as:
CALL TEST_PROC('key2', '2020-02-19 12:17:53');
Then I get an error: "incompatible data type in conversion".
This is a problem for me, since I am not allowed to change the signature of the the stored procedure to bypass the problem, since in my case HSQL is used as a mock for a production database (DB2) where the equivalent procedure works as expected.
It works if you call the procedure with a TIMESTAMP value, as opposed to the character string.
CALL TEST_PROC('key2', TIMESTAMP'2020-02-19 12:17:53');

How to get the restult table of a stored procedure into a temp table?

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 #

abort execution of a stored proc

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

How to define an Array of values (or a Column) into a Procedure Argument?

I am working on a Netezza SP and is stuck with a problem.
I have a SP, defined as say:
CREATE OR REPLACE PROCEDURE MY_PROC(VARCHAR(ANY)) RETURNS INTEGER LANGUAGE NZPLSQL
AS
BEGIN_PROC
DECLARE
v_temp ALIAS FOR $1;
/* Other decalarations */
result_ts INTEGER;
BEGIN
result_ts := 0;
/* Procedure Body */
RETURN result_ts;
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE 'Exception Raised: %', SQLERRM;
END;
END_PROC;
If I am running this SP with one value, such as:
SELECT MY_PROC('TEST_INPUT');
But if I am trying to run it with a column value, such as:
SELECT MY_PROC(TEST_COLUMN) FROM TEST_TABLE;
Its giving me error as:
ERROR: Can't use a stored procedure in this context
I know that in the second scenario I am passing an Array (i guess) but this is not what the Procedure has expected.
Now I am trying to have a procedure that can accept these kind of values but could not succeeded so far, LOOPing and all I have taken care but only problem is the Argument which I don't know how to pass.
Any help would be appreciated, let me know if I need to provide any extra info on this.
Asif
Stored procedures in Netezza, as of v7.2, can only be called in the following ways, as documented here.
CALL sproc_name(...);
EXEC sproc_name(...);
SELECT sproc_name(...);
Note that the SELECT form does not allow a FROM clause.
If you want the stored procedure to act on a particular column from a particular table that changes from invocation to invocation, you could pass the names of those as arguments to the stored procedure and have the entirety of the SQL logic encoded within. You could even pass arbitrary code into the stored procedure to build a query internally.
The way you are trying to call it now is more like calling a user defined function, and that simply won't work with stored procedures here.

DB2 - How do I create a Stored Procedure that ignores errors?

I am trying to create a simple stored procedure in DB2 that performs the following actions:
Drop table "DELETE_ME"
Create table "DELETE_ME"
Insert into table "DELETE_ME"
Basically, if the table DELETE_ME already exists, the stored procedure executes fine. If it does not exist, then the Stored Procedure fails with the following error:
Lookup Error - DB2 Database Error: ERROR [42704] [IBM][DB2/LINUXX8664] SQL0204N "SARTS02T.DELETE_ME" is an undefined name.
I completely understand this. However, I was hoping to set the procedure up to ignore this error (and all errors) that way the procedure can work as a deployment script as well. On the first deployment, it will ignore the drop table line and jump right to building the table.
I found a CREATE PROCEDURE option called CONTINUE AFTER FAILURE however I am receiving an error. Please see my code and error below. Thanks for your help!!!
CODE:
CREATE OR REPLACE PROCEDURE TEST_PROC LANGUAGE SQL CONTINUE AFTER FAILURE
BEGIN
DROP TABLE DELETE_ME;
CREATE TABLE DELETE_ME (
COLUMN_A DECIMAL(5)
);
INSERT INTO DELETE_ME (COLUMN_A) VALUES (69);
COMMIT;
END;
ERROR:
Lookup Error - DB2 Database Error: ERROR [42601] [IBM][DB2/LINUXX8664] SQL0104N An unexpected token "CONTINUE AFTER FAILURE" was found following "ST_PROC LANGUAGE SQL". Expected tokens may include: "<space>".
The BEGIN ... END section is called a compound statement which allows various declarations and other statements, including other compound statements, to be included inside it.
You'll want to declare a condition handler. You could do it something like this.
CREATE OR REPLACE PROCEDURE TEST_PROC
LANGUAGE SQL
COMMIT ON RETURN YES
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '42704' -- or SQLEXCEPTION
BEGIN
-- insert any code here when DROP fails
END;
DROP TABLE DELETE_ME;
CREATE TABLE DELETE_ME
( COLUMN_A DECIMAL(5)
);
INSERT INTO DELETE_ME (COLUMN_A)
VALUES (69);
END;

Resources