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
Related
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 #
Gurus, I have stored procedure to has to executed on a dynamic table. Here is how the stored procedure looks like.
create or replace PROCEDURE EFX_RECON_UPDATE_SPROC(
FILENAME IN VARCHAR2 ,
SOURCE IN VARCHAR2 )
AS
TABLE_NAME VARCHAR2(200);
query_str VARCHAR2(500);
cnt NUMBER(10);
BEGIN
-- Create dynamic table for each fullfilment system.
TABLE_NAME := SOURCE||'_BRM_OMC_RECON_T';
query_str :='SELECT count(*) from ' || SOURCE || '_BRM_OMC_RECON_T where PROCESSINGFILENAME='''||FILENAME||''';';
EXECUTE IMMEDIATE query_str;
query_str:='MERGE INTO '||TABLE_NAME||' T
USING (
SELECT
ERRORCODE, PROCESSINGFILENAME,
RECORDNUMBER from ERROR_UPLOAD_T
) TMP
ON (T.RECORDNUMBER = TMP.RECORDNUMBER and
T.PROCESSINGFILENAME= TMP.PROCESSINGFILENAME and
T.PROCESSINGFILENAME='''||FILENAME||''')
WHEN MATCHED THEN
UPDATE SET
T.STATUS = ''ERROR'',
T.ERRORSOURCE = ''BRM'',
T.ERRORCODE = TMP.ERRORCODE';
EXECUTE IMMEDIATE query_str;
COMMIT;
END EFX_RECON_UPDATE_SPROC;
I get this error while executing the stored procedure. The problem is with FILENAME and I have enclosed it in ' quot.
ORA-00933: SQL command not properly ended
ORA-06512: at "PIN149.EFX_RECON_UPDATE_SPROC", line 12
According to the error message the problem is on this line:
EXECUTE IMMEDIATE query_str;
It should be:
EXECUTE IMMEDIATE query_str INTO cnt;
And the semicolon should be removed from the SELECT string.
Although the variable cnt is not used elsewhere so I'm not sure what that statement is supposed to accomplish.
How to Execute Dynamic DDL statements IN TERADATA?
CREATE PROCEDURE DROP_INDEXES(IN indexs varchar(1000),IN p_database VARCHAR (8000),IN p_table varchar(8000))
BEGIN
DECLARE L_SQL VARCHAR(400);
SET L_SQL= 'DROP INDEX '||trim(indexs)||' ON '||trim(db_name)|| '.'|| trim(tablename);
EXECUTE IMMEDIATE L_SQL;
END ;
I need to call this child_procedure(DROP_INDEXES) from parent procedure, but during executing of the parent_procedure, after executing this procedure
CALL DROP_INDEXES(indexs,db_name,tablename);
automatically gets exit from the parent_procedure, the next statement is not executing from parent_procedure.
This is the error i'm getting:
Executed as Single statement. Failed [3722 : HY000] SP_DROP_INDEXES:
Only a COMMIT WORK or null statement is legal after a DDL Statement.
Elapsed time = 00:00:00.326
Kindly do help me regarding my issue.
Thanks in advance.
In Teradata each DDL must be committed individually. Your session is running in ANSO mode, thus you need to add ;COMMIT; to the SQL string.
This should work:
SET L_SQL= 'DROP INDEX '||trim(indexs)||' ON '||trim(db_name)|| '.'|| trim(table name) || ';COMMIT;'
Try a different syntax:
REPLACE PROCEDURE DROP_INDEXES(IN indexs varchar(1000), IN p_database VARCHAR (8000),IN p_table varchar(8000))
BEGIN
DECLARE L_SQL VARCHAR(400);
SET L_SQL= 'DROP INDEX '||trim(indexs)||' ON '||trim(p_database)|| '.'|| trim(p_table);
--EXECUTE IMMEDIATE L_SQL;
CALL DBC.SysExecSQL( L_SQL );
END ;
REPLACE PROCEDURE PROC_TEST1 (IN db_name varchar(30),IN tablename varchar(30),IN indexs varchar(30))
BEGIN
CALL DROP_INDEXES(indexs,db_name,tablename);
insert into test2 (charcol) select user;
END;
call proc_test1(DATABASE,'test2','idx_test2');
I am running an Oracle 9i server at my office. I am working on a procedure that passes a sys_refcursor as an out parameter to another package (along with other in parameters). I was able to define a type as a record of the various columns that the called procedure returns in the cursor. I can then loop over with code like this:
LOOP
fetch o_results into v_rec;
exit when o_results%notfound;
dbms_output.put_line(v_rec.some_id);
end loop;
Is there a way to only pull one column and not have to declare an entire rowtype? I tried something like:
LOOP
fetch o_results.some_id into v_id;
exit when o_results%notfound;
dbms_output.put_line(v_id);
end loop;
But that didn't work. Any other ideas?
No, you cannot fetch a single column into a local variable other than a record if the cursor returns a result set with multiple columns. However, you do have a few alternatives.
If you declare a strongly-typed cursor rather than a weakly typed cursor, you could declare your local variable based on that cursor definition rather than declaring a new collection.
create or replace procedure cursor_proc
as
cursor emp_cur
is
select empno, ename
from emp;
l_row emp_cur%rowtype;
begin
open emp_cur;
loop
fetch emp_cur into l_row;
exit when emp_cur%notfound;
dbms_output.put_line( l_row.ename );
end loop;
close emp_cur;
end;
Alternately, if you know that the weakly typed ref cursor will always return all the columns in a particular object, you can anchor your local variable declaration to that object. You can always make this work by declaring a view that your cursor selects from. For example
create or replace view vw_emp
as
select ename, empno
from emp
create or replace procedure cursor_proc2
as
emp_cur sys_refcursor;
l_row vw_emp%rowtype;
begin
open emp_cur for select * from vw_emp;
loop
fetch emp_cur into l_row;
exit when emp_cur%notfound;
dbms_output.put_line( l_row.ename );
end loop;
close emp_cur;
end;
Finally, if you use an implicit cursor, Oracle will implicitly declare the collection type
create or replace procedure cursor_proc3
as
begin
for emp in (select ename, empno from emp)
loop
dbms_output.put_line( emp.ename );
end loop;
end;