Dynamic Stored Procedure in Oracle - stored-procedures

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.

Related

Dynamic SQL calling another stored procedure in Teradata

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;

How can I check if a stored procedure exists in PERVASIVE database before creating it?

I want to create a stored procedure in a Pervasive database, but only if it does not yet exist.
I found something for SQL Server:
IF NOT EXISTS (SELECT *
FROM sys.objects
WHERE type = 'P' AND OBJECT_ID = OBJECT_ID('dbo.MyProc'))
exec('CREATE PROCEDURE [dbo].[MyProc] AS BEGIN SET NOCOUNT ON; END')
GO
I found that code on this link How to check if a stored procedure exists before creating it.
So I want something really similar for Pervasive.
There's no way to execute the IF NOT EXISTS syntax outside of a Stored Procedure in Pervasive. You could create a procedure taking a procedure name and drop it if it exist. Something like:
CREATE PROCEDURE DropProcIfExists(in :procname char(20))
AS
BEGIN
IF( EXISTS (SELECT xp$Name FROM X$proc WHERE Xp$Name = :procname) ) THEN
Exec('DROP Procedure "' + :procname + '"') ;
END IF;
End#
call DropProcIfExists ('myProc')#
So your SQL would be something like:
call DropProcIfExists('MyNewProc')#
Create Procedure MyNewProc()
AS
BEGIN...

Execute Dynamic DDL statement in teradata stored procedure?

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');

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

PLSQL call procedure from function

I have a function which is called from a select query, below is the function which works perfect. I want to call the procedure below if boolean = 1 that inserts values into the login table:
create or replace FUNCTION isLoggedIn(x IN VARCHAR2, y IN VARCHAR2)
RETURN number IS
boolean number(1) := 0;
BEGIN
SELECT count(*) into boolean
FROM VIEWLOGIN
WHERE username = x AND password = y;
IF boolean = 1 THEN
PROCDURELOGIN
RETURN boolean;
ELSE
RETURN 0;
END IF;
END;
This is my procedure:
create or replace PROCEDURE PROCDURELOGIN
IS
BEGIN
INSERT INTO "SW3"."LOGIN" (LOGINID, MEMBERID)
VALUES (seqLogin.NEXTVAL, '1');
Commit;
END;
Create view VIEWLOGIN
SELECT firstname, surname, username, password
FROM member
But I get the error when I run the query:
Error starting at line : 1 in command -
SELECT firstname, surname, isLoggedIn(username, password)
FROM VIEWLOGIN
WHERE username = 'fionawalshe' AND password = 'qwertyu8'
Error report -
SQL Error: ORA-14551: cannot perform a DML operation inside a query
ORA-06512: at "SW3.PROCDURELOGIN", line 4
ORA-06512: at "SW3.ISLOGGEDIN", line 10
14551. 00000 - "cannot perform a DML operation inside a query "
*Cause: DML operation like insert, update, delete or select-for-update
cannot be performed inside a query or under a PDML slave.
*Action: Ensure that the offending DML operation is not performed or
use an autonomous transaction to perform the DML operation within
the query or PDML slave.
Oracle clearly says in the error message, what is a problem. Try this:
create or replace PROCEDURE PROCDURELOGIN
IS
pragma autonomous_transaction;
BEGIN
INSERT INTO "SW3"."LOGIN" (LOGINID, MEMBERID)
VALUES (seqLogin.NEXTVAL, '1');
Commit;
END;
By the way, I don't like such procedures and recommend not to use them, if possible.

Resources