Oracle Dynamic delete statements with DECODE Function - oracle

Hi I have the following procedure:
create or replace procedure
SP_DELETE_FROM_TABLE(pTableName in VARCHAR2, pFieldName in VARCHAR2,
pFieldValue in VARCHAR2,pFieldType in VARCHAR2) is
querystring VARCHAR2(500);
begin
queryString := 'DELETE FROM ' ||pTableName||
' WHERE '||pFieldName ||' = DECODE(:pFieldType,integer,:pFieldValue)' ;
EXECUTE IMMEDIATE queryString USING pFieldType,pFieldValue;
end SP_DELETE_FROM_TABLE;
all my Parameters are of Type VARCHAR2, What I am trying to do is: When I call the procedure with the following values ('users_table','users_id','11','integer')
so by using DECODE I would like to check if pFieldValue is of type pFieldTypeand if yes return pFieldValue
so if pFieldValue is:11 and pfieldType is:integer it should delete users_id 11 if fieldType is string do nothing..

I'd create a function that checks parameter has correct type
and then use it in main procedure
--main procedure
create or replace procedure SP_DELETE_FROM_TABLE(pTableName in VARCHAR2, pFieldName in VARCHAR2,pFieldValue in VARCHAR2,pFieldType in VARCHAR2) is
querystring VARCHAR2(500);
begin
if 'Y' = is_type_correct(pFieldValue, pFieldType ) then
queryString := 'DELETE FROM ' ||pTableName|| ' WHERE '
||pFieldName ||' = :pFieldValue';
EXECUTE IMMEDIATE queryString USING pFieldValue;
end
else
null; --incorrect type and parameter, do nothing
end;
end SP_DELETE_FROM_TABLE;
--check function
CREATE OR REPLACE FUNCTION is_type_correct( p_val IN VARCHAR2, p_type varchar2 )
RETURN VARCHAR2 DETERMINISTIC PARALLEL_ENABLE
IS
l_num NUMBER;
l_date date;
BEGIN
if 'integer' = p_type
then
l_num := to_number( p_val );
elsif 'date' = p_type then
l_date := to_date(p_val, 'YYYY.MM.DD');
elsif 'varchar2' then
null;//do nothing
else
return 'N'; //uknown type
end if;
RETURN 'Y';
EXCEPTION
WHEN value_error THEN
RETURN 'N';
END is_number;

Just try to convert a string to a number, and when an exception occurs, do nothing:
querystring VARCHAR2(500);
some_number number;
begin
some_number := to_number( pFieldValue ); /* trying to convert to a number */
queryString := 'DELETE FROM ' ||pTableName||
' WHERE '||pFieldName ||' = :x' ;
EXECUTE IMMEDIATE queryString USING some_number;
EXCEPTION
WHEN VALUE_ERROR THEN null; /* do nothing when pFieldValue is not a number*/
end SP_DELETE_FROM_TABLE;

Related

how to return null if no data found from a function with return type sys_refcursor?

whenever i call this function it will return error like - invalid cursor
so, this is the body part of the package, the package specification also return a sys_refcursor. the error message shows that sys_refcursor invalid cursor.
FUNCTION SUMMARY
(i_name VARCHAR2, i_id VARCHAR2, i_label VARCHAR2)
RETURN SYS_REFCURSOR
IS
rc_result SYS_REFCURSOR;
v_sql CLOB;
Server VARCHAR2(100) := '#AI';
v_r_count NUMBER;
v_sp_count VARCHAR2(200);
V VARCHAR2(10);
BEGIN
EXECUTE IMMEDIATE 'select count(*) from run'||Server||' where id='''||i_id||''' and label='''||i_label||''' and re is not null' INTO v_r_count;
EXECUTE IMMEDIATE 'select table_name from all_tables where table_name like ''%se%'' and owner ='''||i_name||'''' INTO v_sp_count;
IF v_r_count > 0 THEN
BEGIN
v_sql := 'select RE from run'||v_Server||' where id='''||i_id||''' and label='''||i_label||'''';
END;
ELSIF v_sp_count IS NOT NULL THEN
BEGIN
v_sql := 'SELECT
process,
desc,
p_desc,
date
FROM
'||i_name||'.se
WHERE
errors = 1
AND lower(p_desc) LIKE lower(''%summary%'')';
END;
ELSE v_sql := NULL;
END IF;
OPEN result FOR v_sql;
RETURN result;
EXCEPTION
WHEN no_data_found THEN
RETURN NULL;
WHEN OTHERS THEN
dbms_output.put_line(SQLERRM);
END;
You can simply assign NULL to the refcursor like this: Example
PROCEDURE test( id_number IN VARCHAR2,
resultIN OUT SYS_REFCURSOR) AS
BEGIN
if false then
OPEN resultIN FOR
SELECT dummy
from dual;
ELSE
resultIN := null;
END IF;
END;

bind variable error in stored procedure

Here is my procedure code :
create or replace Procedure SP_CUSTOMER_PRODUCT_QRY
( PARENT_PARTYID IN varchar2,PRODUCT_ID IN varchar2,PRODUCT_STATUS IN varchar2,PAGING IN varchar2,OFFSET IN varchar2,LIST_OF_PARTIES OUT VARCHAR2 )
AS
V_SQL_WHERE varchar2(10000):= null;
V_SQL varchar2(10000):='SELECT PARTYID FROM TABLE1';
V_check varchar2(10000) := '' ;
BEGIN
IF(PARENT_PARTYID IS NOT NULL) THEN
V_SQL_WHERE := V_SQL_WHERE || ' PARENT_PARTYID=:1';
END IF;
IF(PRODUCT_ID IS NOT NULL) THEN
IF (V_SQL_WHERE is not null) THEN
V_SQL_WHERE := V_SQL_WHERE || ' AND ';
END IF;
V_SQL_WHERE := V_SQL_WHERE || ' PRODUCT_ID=:2';
END IF;
IF(PRODUCT_STATUS IS NOT NULL) THEN
IF (V_SQL_WHERE is not null) THEN
V_SQL_WHERE := V_SQL_WHERE || ' AND ';
END IF;
V_SQL_WHERE := V_SQL_WHERE || ' PRODUCT_STATUS=:3';
END IF;
IF (V_SQL_WHERE is not null) then
V_SQL := V_SQL || ' WHERE ' || V_SQL_WHERE;
end if;
dbms_output.put_line(V_SQL);
EXECUTE IMMEDIATE V_SQL INTO LIST_OF_PARTIES;
EXCEPTION
WHEN NO_DATA_FOUND THEN
V_check:= '' ;
END;
I have used bind variables ,unable to understand the issue.Is it mandatory to bind all parameters even if they are not used in procedure
When I am passing any input I am getting error as
java.sql.SQLException: ORA-01008: not all variables bound
In this case there is no need for using dynamic plsql. Try to do this this way:
CREATE OR REPLACE PROCEDURE SP_CUSTOMER_PRODUCT_QRY
( P_PARENT_PARTYID IN VARCHAR2,
P_PRODUCT_ID IN VARCHAR2,
P_PRODUCT_STATUS IN VARCHAR2,
P_PAGING IN VARCHAR2,
P_OFFSET IN VARCHAR2,
P_LIST_OF_PARTIES OUT VARCHAR2 )
AS
CURSOR CUR_PARTYID
IS
SELECT PARTYID
FROM TABLE1
WHERE (P_PARENT_PARTYID IS NULL
OR PARENT_PARTYID = P_PARENT_PARTYID)
AND (P_PRODUCT_ID IS NULL
OR PRODUCT_ID = P_PRODUCT_ID)
AND (P_PRODUCT_STATUS IS NULL
OR PRODUCT_STATUS = P_PRODUCT_STATUS);
BEGIN
OPEN CUR_PARTYID;
FETCH CUR_PARTYID INTO P_LIST_OF_PARTIES;
CLOSE CUR_PARTYID;
END;
/
You need the "using" clause with your execute immediate for the 3 variables in the where clause.
for example:
EXECUTE IMMEDIATE 'DELETE FROM dept WHERE deptno = :num' USING dept_id;

String Compare in Oracle Procedure

Trying to compare two string. one from IN parameter(myname) and another is Hard coded('abcd').
(myname IN VARCHAR2)
-- myname will be set to 'abcd' when calling this procedure
DECLARE
name VARCHAR2(10):=myname;
IF(name='abcd') THEN
--update something in database
END IF;
Actual code is given below. idegreeName is set to 'HONS'. if I remove if block then my procedure works fine. but I need IF block to execute update query.
// Calling in JAVA
stmt = (OracleCallableStatement) conn.prepareCall("{ call receiveAdmission2(?,?,?,?,?,?,?,?,?,?,?,?,?,?) }");
// my procedure
CREATE OR REPLACE PROCEDURE NU_DB.receiveAdmission2 (
iAdmissionRoll IN VARCHARARRAY,
iUserId IN VARCHAR2,
iCollegeCode IN VARCHAR2,
isessionId IN VARCHAR2,
isubjectId IN VARCHAR2,
iMeritType IN VARCHAR2,
iStatus IN VARCHAR2,
iXforward IN VARCHAR2,
iVia IN VARCHAR2,
iRemoteAddress IN VARCHAR2,
oResponseCode OUT NUMBER,
oResponseMessage OUT VARCHAR2,
oResponse OUT VARCHAR2,
idegreeName IN VARCHAR2
)
IS
tErrorCode VARCHAR2(20);
tErrorMsg VARCHAR2(400);
tResponse VARCHAR2(100);
BEGIN
oResponse:='';
DECLARE
str1 VARCHAR2(10):=idegreeName;
Begin
FOR i IN 1 .. iAdmissionRoll.COUNT
LOOP
IF(str1='HONS') THEN
UPDATE nu_hons_result set STATUS=iStatus where ADMISSION_ROLL=iAdmissionRoll(i) and MERIT_TYPE=iMeritType and COLLEGE_CODE=iCollegeCode and SUBJECT_ID=isubjectId and STATUS='Student Requested';
END IF;
if (sql%rowcount > 0) then
tResponse := 'Successfully approved.';
if(iMeritType<>5) then
UPDATE nu_college_subject_map set AVAILABLE_SEAT=AVAILABLE_SEAT-1 where SESSION_ID=isessionId and COLLEGE_CODE=iCollegeCode and SUBJECT_ID=isubjectId;
end if;
insert into NU_HONS_SUBJECT_ADMISSION (ADMISSION_ROLL,SESSION_ID,COLLEGE_CODE,SUBJECT_ID,APPROVED_BY,APPROVED_ON)
values(iAdmissionRoll(i),isessionId,iCollegeCode,isubjectId,iUserId,sysdate);
insert into nu_log_admission values (iAdmissionRoll(i),isessionId,iCollegeCode,iMeritType,iStatus,sysdate,isubjectId);
else
tResponse := 'Failed to approve.'||idegreeName;
end if;
oResponse := oResponse || tResponse || '###';
END LOOP;
EXCEPTION WHEN DUP_VAL_ON_INDEX THEN
tErrorCode:=SQLCODE;
tErrorMsg:=SUBSTR(SQLERRM, 1, 400);
oResponseCode := 1;
oResponseMessage :=tErrorMsg;
ROLLBACK;
Return;
WHEN OTHERS THEN
tErrorCode:=SQLCODE;
tErrorMsg:=SUBSTR(SQLERRM, 1, 400);
oResponseCode := 2;
oResponseMessage :=tErrorMsg;
ROLLBACK;
Return;
End;
END receiveAdmission2;
/
Problem is IF block is not executing.
Youre code works like expected. I added logging for test purposes. Show how you call the code or add logging for the parameters and work from there
DECLARE name VARCHAR2(10);
BEGIN
name := 'abcd';
IF ( name = 'abcd') THEN
dbms_output.put_line('equal');
ELSE
dbms_output.put_line('NOT equal');
END IF;
END;

Oracle Create Function

I tried to create an Oracle function where table name, column name and where string are dynamic parameters:
CREATE OR REPLACE FUNCTION MYSCHEMA.myFunctionName(
tableName in nvarchar2,
columnName in nvarchar2,
whereStr in nvarchar2)
RETURN nvarchar2
IS nActive nvarchar2(2000);
BEGIN
declare
querystr nvarchar2(2000) ;
result nvarchar2(2000);
begin
querystr :='
select listagg('+columnName+','+','+') within group (order by '+columnName+')
from '+tableName+' where 1 = 1 '+whereStr+';';
EXECUTE IMMEDIATE querystr
INTO result;
nActive := result;
RETURN ( nActive );
end;
END ;
/
But it gives me error "Warning: compiled but with compilation errors".
What am I doing wrong?
For concatenate strings in Oracle use || not +
You don't need ; at the end of execute immediate query string
You need to escape ' using ''.
... as #Aleksej said
Execute immediate need query string in CHAR or VARCHAR2;
listagg return either raw or VARCHAR2
CREATE OR REPLACE FUNCTION MYSCHEMA.myFunctionName(
tableName in varchar2,
columnName in varchar2,
whereStr in varchar2)
RETURN varchar2
BEGIN
declare
querystr varchar2(2000) ;
result varchar2(2000);
begin
querystr :='
select listagg('|| columnName || ', '','') within group (order by ' ||columnName ||')
from ' || tableName || ' where 1 = 1 ' || whereStr;
EXECUTE IMMEDIATE querystr INTO result;
return result;
end;
END ;
/
You need to change the type of your variables, considering that
"The return data type is RAW if the measure column is RAW; otherwise the return value is VARCHAR2" (documentation)
EXECUTE needs a VARCHAR2: "It must be of type CHAR or VARCHAR2, not NCHAR or NVARCHAR2"
So:
declare
querystr varchar2(2000) ;
result VARCHAR2(32767);
begin
...

Odp.net fails with ORA-000942 (table or view does not exist)

Attempting to execute package stored procedure using ODP.NET
The call fails with message "ORA-00942: table or view does not exist\nORA-06512: at \"SAAP.PKGPRICEWORX\", line 25\nORA-06512:....
However the procedure works fine when run though the server server explorer !.
I am using ODP.net4 assemblies on VS2010;
Any help to resolve this appreciated.
Here is the package:
clear;
/
create or replace
PACKAGE pkgPriceWorx
AS
defaultQANP NUMBER:=99999999;
procedure dbg(s varchar2,INDENT NUMBER DEFAULT 0,APPEND NUMBER DEFAULT 0);
FUNCTION frSls031CunoCpgsStdt( comno VARCHAR2,cuno VARCHAR2,cpgs VARCHAR2,stdt DATE,found OUT NUMBER)RETURN baan.ttdsls031010%rowtype ;
FUNCTION frSLS034( comno VARCHAR2, cuno VARCHAR2, cpgs VARCHAR2, found OUT NUMBER) RETURN baan.ttdsls034010%rowtype;
PROCEDURE prUpdateOrInsertDiscount( COMNO VARCHAR2 , CPLS VARCHAR2, CUNO VARCHAR2 , CPGS VARCHAR2, stdt DATE , DISC IN OUT NUMBER, O OUT VARCHAR2);
PROCEDURE prUpdateSLS031(R2U baan.ttdsls031010%rowtype,Comno varchar2, RowsUpdated out number);
PROCEDURE prUpdateOrInsertSLS034( comno VARCHAR2, cuno VARCHAR2, cpgs VARCHAR2, rowCount OUT NUMBER) ;
FUNCTION fnDefaultQANP RETURN NUMBER ;
procedure testNumPrecision(precie number);
END ;
/
show error;
/
create or replace
PACKAGE BODY pkgPriceWorx IS
spc varchar2(1):=' ';
jed varchar2(10):='1,J';-- Julian Expiry format
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------
procedure dbg(s varchar2,INDENT NUMBER DEFAULT 0,APPEND NUMBER DEFAULT 0) as
BEGIN
if append =0 then
BEGIN
DBMS_output.Put_line(s);
END;
else
BEGIN
dbms_output.Put(s);
end;
End if;
END;
-------------------------------------------------------------------------------------
procedure prInsertSLS031(comno varchar2,cuno varchar2,cpgs varchar2,stdt Date,disc number, rowCount out number) as
sQ varchar2(3000);
BEGIN
dbms_output.put_line('#prInsertSLS031');
sQ:= ' Insert into baan.ttdsls031' ||comno|| '(t$cuno,t$cpgs,t$dile,t$qanp ,t$stdt ,t$tdat ,t$disc ,t$damt,t$cdis,t$gnpr,t$refcntd,t$refcntu)' || ' values( :cuno,:cpgs ,1 ,:qanp ,:stdt ,to_date('||'''1' || ''' ,'||'''J '''||') ,:disc ,0 ,' || ''' '''||' ,1 ,0 ,0)';
dbms_output.put_line(sQ);
EXECUTE immediate sQ USING cuno,cpgs,defaultqanp,STDT,disc;
rowCount:=sql%rowcount;
END;
-----------------------------------------------------------------------------------
PROCEDURE prUpdateOrInsertDiscount(COMNO VARCHAR2 ,CPLS VARCHAR2, CUNO VARCHAR2 , CPGS VARCHAR2 , stdt date, DISC in out NUMBER ,O out varchar2) AS
R31 BAAN.TTDSLS031010%ROWTYPE;
R34 BAAN.TTDSLS034010%ROWTYPE;
rowCount number;
sQ varchar2(3000);
rc number;
edt date;
iRC number;
uRc number;
BEGIN
/*------------------------------------------------------------------
1). Check SLS031.DISC(Customer and priceGroup, ?OPEN)
1.1) If a match found
1.2.1) Compare NewDiscount == current
return :
1.2.2) NewDisc != CURRENT
I . Update current to expire
II. Insert an entry
2.1) If No match found
I . insert new 31 entry
IDX1=CUNO,CPGS,DILE
?open=tdat=4712-01-01;
----------------------------------------------------------------*/
DBG('#prUpdateOrInsertDiscount');
R31:=frSLS031CunoCpgsStdt(COMNO,cuno,cpgs,stdt,rowCount );
DBMS_OUTPUT.PUT_LINE('ROW COUNT ON FRSLS031='|| ROWCOUNT);
IF (rowCount > 0) then -- 1.1 Match found
BEGIN
dbg('Match found');
if((stdt ) > R31.T$STDT Or (disc != R31.t$disc)) then
Begin
dbg('Ok : OpenRecord has stdt > (stdt-1)');
r31.t$tdat:=stdt-1;
prUpdateSLS031(R31,comno,uRc);
dbg('Updated rowCount ='||urc);
prInsertSLS031(comno,cuno,cpgs,stdt,disc, rowCount);
return;
End;
end if;
dbg('Both stdt and disc has no change.. nothing was done');
END;
ELSE -- NO NMATCH
Begin
dbg( ' No Match inserting new ' );
prInsertSLS031(comno,cuno,cpgs,stdt,disc,rowCount);
End;
END IF;
END prUpdateOrInsertDiscount;
----------------------------------------------------------------------------------
PROCEDURE prUpdateOrInsertSLS034(comno varchar2,cuno varchar2, cpgs varchar2,rowCount out number) AS
R baan.ttdsls034010%rowtype;
sQ varchar2(3000);
rc number;
cpls varchar2(3);
cuni varchar2(3);
BEGIN
R:=frSls034(comno,cuno,cpgs,rc);
if (rc > 0 ) then return; end if;
cpls :=' ';
cuni :='ea';
-- sQ:='insert into baan.ttdsls034' ||comno|| '(t$cuno,t$cpgs ,t$dile,t$APYN,T$CPLS,T$STSA,T$STSB,T$STSC,T$KOGR,T$CUNI,T$DMTH,T$REFCNTD,T$REFCNTU)' ;
-- ' VALUES(:CUNO ,:CPGS ,1 ,2 ,:CPLS ,2 ,2 ,2 ,1 , :CUNI ,1 ,0 ,0)';
dbms_output.put_line(sQ);
execute immediate sQ using cuno,cpgs,cpls,cuni;
END prUpdateOrInsertSLS034;
-----------------------------------------------------------------------------------
function fnDefaultQANP return number is n number;
Begin
return defaultQANP;
End;
-----------------------------------------------------------------------------------
function frSls031CunoCpgsStdt(comno varchar2,cuno varchar2,cpgs varchar2,stdt date,found out number) return baan.ttdsls031010%rowtype is
r baan.ttdsls031010%rowtype;
sQ varchar2(600);
BEGIN
sQ :='SELECT * FROM BAAN.TTDSLS031'||COMNO || ' WHERE ' ||
' TRIM(T$CUNO)=trim( :CUNO) AND ' || ' TRIM(T$CPGS)=trim( :CPGS) AND ' ||
' T$QANP = :qanp AND ' ||
' t$tdat =(select MIN(t$tdat) from baan.ttdsls031'||comno||' where trim(t$cuno)=trim(:cuno) ' ||
' and trim(t$cpgs)=trim(:cpgs) and t$qanp=:qanp) ';
execute immediate sQ into r using cuno,cpgs,fndefaultQanp,cuno,cpgs,fndefaultQanp;
found:=sql%rowcount;
RETURN R;
exception
when
no_data_found then found:=-1;
return null;
end;
-------------------------------------------------------------
function frSLS034(comno varchar2,cuno varchar2,cpgs varchar2,found out number) return baan.ttdsls034010%rowtype is
r baan.ttdsls034010%rowtype;
sQ varchar2(3000);
BEGIN
sQ :='SELECT * FROM BAAN.TTDSLS034'||COMNO || ' WHERE' || ' TRIM(T$CUNO)= trim(:CUNO) AND ' || ' TRIM(T$CPGS)=trim( :CPGS)';
EXECUTE immediate sQ INTO r USING cuno,cpgs;
FOUND:=SQL%ROWCOUNT;
RETURN R;
EXCEPTION
WHEN no_data_found THEN
found:=-1;
return null;
END;
----
PROCEDURE prUpdateSLS031(R2U baan.ttdsls031010%rowtype,Comno varchar2,RowsUpdated out number) as
sQ varchar2(3000);
Begin
sQ:='update baan.ttdsls031'||comno|| ' set t$tdat=:rtdat where t$cuno=:cuno and t$cpgs=:cpgs and t$dile=:dile and t$qanp=:qanp and t$stdt = :stdt ';
dbg( '#prUpdateSLS031');
dbg(' '||sQ);
execute immediate SQ using R2U.t$tdat , R2U.t$cuno , R2U.t$cpgs , R2U.t$dile , R2U.t$qanp , R2U.t$stdt;
RowsUpdated:=Sql%rowCount;
End ;
----
procedure testNumPrecision(precie number)as
Begin
null;
end;
-------------------------------------------------------------
-------------------------------------------------------------
END pkgPriceWorx;
/
show error;
/
Sorry folks for bothering you and thanks to Justin Cave for hinting where could be the error, It was a error in the net code, in which I had lopped a character in the parameter name, so when the dynamic sql was constructing the code, it did not find the parameter specified (which is suffix of the one of the table).

Resources