Executing stored procedure based on table column value - sql

I am trying to return result from table based on value returned from another table column.
I am getting error when no data is found in user_config table. I want else part to execute instead.
CREATE OR REPLACE PROCEDURE valuefinders (
in_soeid IN VARCHAR2,
out_cursor OUT SYS_REFCURSOR
) AS
group1 VARCHAR2(128 BYTE) := 'n';
BEGIN
SELECT
admin
INTO group1
FROM
user_config
WHERE
soeid = in_soeid;
IF ( group1 = 'y' ) THEN
OPEN out_cursor FOR SELECT
*
FROM
user_profile;
ELSE
OPEN out_cursor FOR SELECT
*
FROM
user_request;
END IF;
END valuefinders;```

You can also nest exceptions in your code itself and take advantage of them.
This example shows that when the query on user_config raises a NO_DATA_FOUND, the variable group1 is set to 'n' and the else block will be executed:
CREATE OR REPLACE PROCEDURE valuefinders (
in_soeid IN VARCHAR2,
out_cursor OUT SYS_REFCURSOR
) AS
group1 VARCHAR2(128 BYTE) := 'n';
BEGIN
BEGIN
SELECT
admin
INTO group1
FROM
user_config
WHERE
soeid = in_soeid;
EXCEPTION WHEN NO_DATA_FOUND THEN
group1 := 'n';
END;
IF ( group1 = 'y' ) THEN
OPEN out_cursor FOR SELECT
*
FROM
user_profile;
ELSE
OPEN out_cursor FOR SELECT
*
FROM
user_request;
END IF;
END valuefinders;

Handle the exception, somehow. The simplest option is to do nothing:
CREATE OR REPLACE PROCEDURE valuefinders (in_soeid IN VARCHAR2,
out_cursor OUT SYS_REFCURSOR)
AS
group1 VARCHAR2 (128 BYTE) := 'n';
BEGIN
SELECT admin
INTO group1
FROM user_config
WHERE soeid = in_soeid;
IF (group1 = 'y')
THEN
OPEN out_cursor FOR SELECT * FROM user_profile;
ELSE
OPEN out_cursor FOR SELECT * FROM user_request;
END IF;
EXCEPTION --> here
WHEN NO_DATA_FOUND
THEN
NULL;
END valuefinders;
If you want to do something else, then just do it:
EXCEPTION
WHEN NO_DATA_FOUND
THEN
OPEN out_cursor FOR SELECT * FROM user_request;

Related

how to pass where in clause values in stored procedure in Oracle Sql

I have a procedure which takes parameter as a string in comma seperated format like "Saved,In Progress". Below procedure is working fine with on one status like "Saved". but not working with comma seprated values
create or replace PROCEDURE get_Sample_request (
in_request_status IN VARCHAR2,
out_cursor OUT SYS_REFCURSOR
) AS
sql_qry VARCHAR2 (150);
emp_tot NUMBER(3);
BEGIN
OPEN out_cursor FOR SELECT * from user_requests where request_status in (in_request_status);
END get_Sample_request;
Use LIKE:
create or replace PROCEDURE get_Sample_request (
in_request_status IN VARCHAR2,
out_cursor OUT SYS_REFCURSOR
) AS
sql_qry VARCHAR2 (150);
emp_tot NUMBER(3);
BEGIN
OPEN out_cursor FOR
SELECT *
FROM user_requests
WHERE ',' || in_request_status || ',' LIKE '%,' || request_status || ',%';
END get_Sample_request;
/
Or, pass in a collection:
create or replace PROCEDURE get_Sample_request (
in_request_status IN SYS.ODCIVARCHAR2LIST,
out_cursor OUT SYS_REFCURSOR
) AS
sql_qry VARCHAR2 (150);
emp_tot NUMBER(3);
BEGIN
OPEN out_cursor FOR
SELECT *
FROM user_requests
WHERE request_status IN (SELECT column_value FROM TABLE(in_request_status));
END get_Sample_request;
/
Or, split the string (slower):
create or replace PROCEDURE get_Sample_request (
in_request_status IN VARCHAR2,
out_cursor OUT SYS_REFCURSOR
) AS
sql_qry VARCHAR2 (150);
emp_tot NUMBER(3);
BEGIN
OPEN out_cursor FOR
SELECT *
FROM user_requests
WHERE request_status IN (SELECT REGEXP_SUBSTR(in_request_status, '[^,]+', 1, LEVEL)
FROM DUAL
CONNECT BY LEVEL <= REGEXP_COUNT(in_request_status, '[^,]+'));
END get_Sample_request;
/

Update trigger not updating timestamp(update operation) in column

Trigger not working while updating the table column with trigger enabled on table...
CREATE OR REPLACE Trigger TR_FinlStatAssetDesignation_U
BEFORE Update
on FINLSTATASSETDESIGNATION FOR EACH ROW
DECLARE
v_AtDateTime TIMESTAMP(3);
v_LogOperation NUMBER(3,0);
v_UserName VARCHAR2(255);
v_AppName VARCHAR2(255);
SWV_error NUMBER(10,0) DEFAULT 0;
BEGIN
begin
select USERNAME INTO v_UserName FROM v$session WHERE (audsid = SYS_CONTEXT('userenv','sessionid')) AND ROWNUM <=1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
end;
SELECT program INTO v_AppName FROM v$session WHERE audsid=userenv('sessionid');
if (LENGTH(v_AppName) = 0) then
v_AppName := 'Unknown';
end if;
SELECT distinct TO_CHAR(SYSTIMESTAMP,'DD-MON-YY hh24:mi:SS.FF AM') INTO v_AtDateTime FROM dual;
if UPDATING('FinlStatAssetDesignation') then
RAISE_APPLICATION_ERROR(-20000,'Invalid attempt to update OID FinlStatAssetDesignation in FinlStatAssetDesignation');
/*
ROLLBACK */
return;
end if;
if not UPDATING('UpdDate') then
SWV_error := 0;
begin
UPDATE FinlStatAssetDesignation a SET(UpdDate) =(SELECT distinct v_AtDateTime FROM dual where a.FinlStatAssetDesignation = :NEW.FinlStatAssetDesignation)
WHERE ROWID IN(SELECT a.ROWID FROM FinlStatAssetDesignation a where a.FinlStatAssetDesignation = :NEW.FinlStatAssetDesignation);
EXCEPTION
WHEN OTHERS THEN
SWV_error := SQLCODE;
end;
if SWV_error <> 0 then
/*
ROLLBACK */
return;
end if;
end if;
END;
QL> select * from finlstatassetdesignation;
FINLSTATAS FINLSTATASSETDESIGNATIONDESC UPDOPERATION
---------- -------------------------------------------------- ------------
UPDDATE
---------------------------------------------------------------------------
one19 anything 0
01-JAN-17 08.00.00.000000 AM
SQL> update finlstatassetdesignation set finlstatassetdesignationdesc ='nothing';
1 row updated.
SQL> select * from finlstatassetdesignation;
FINLSTATAS FINLSTATASSETDESIGNATIONDESC UPDOPERATION
---------- -------------------------------------------------- ------------
UPDDATE
---------------------------------------------------------------------------
one19 nothing 0
01-JAN-17 08.00.00.000000 AM
SQL> desc finlstatassetdesignation;
Name Null? Type
----------------------------------------- -------- ----------------------------
FINLSTATASSETDESIGNATION NOT NULL CHAR(10 CHAR)
FINLSTATASSETDESIGNATIONDESC NOT NULL VARCHAR2(50 CHAR)
UPDOPERATION NOT NULL NUMBER(10)
UPDDATE NOT NULL TIMESTAMP(6)
Trying to update column FINLSTATASSETDESIGNATIONDESC gets succeded however doesnt update the timestamp in column UPDDATE
Please help....in fixing this trigger...
Trigger not working while updating the table column with trigger enabled on table...
Usually it is a bad idea to write strings (i.e. TO_CHAR(SYSTIMESTAMP,'DD-MM-YY hh24:mi:SS.FF AM') INTO v_AtDateTime) when you actually want to write timestamps.
There are several weak points in your code, according to my understanding you can write it simpler:
CREATE OR REPLACE TRIGGER TR_FinlStatAssetDesignation_U
BEFORE UPDATE
ON FINLSTATASSETDESIGNATION FOR EACH ROW
BEGIN
IF UPDATING('FinlStatAssetDesignation') THEN
RAISE_APPLICATION_ERROR(-20000,'Invalid attempt to update OID FinlStatAssetDesignation in FinlStatAssetDesignation');
-- Rather strange if a column has the same name as the table
END IF;
IF NOT UPDATING('UpdDate') THEN
:NEW.UpdDate := SYSTIMESTAMP;
END IF;
END;
Everything else in your code is redundant, resp. junk.
In case you need the username somewhere, just write USER instead of
select USERNAME INTO v_UserName
FROM v$session
WHERE (audsid = SYS_CONTEXT('userenv','sessionid')) AND ROWNUM <=1;
For application use NVL(SYS_CONTEXT('USERENV', 'CLIENT_PROGRAM_NAME'), 'Unknown') instead of
SELECT program INTO v_AppName FROM v$session WHERE audsid=userenv('sessionid');
if (LENGTH(v_AppName) = 0) then
v_AppName := 'Unknown';
end if;

PL/SQL if table not exist create

Hello i use oracle SQL developer
I have create a procedure, and i need to check if a table exist, if not exist i must create how can do?
I have try this
DECLARE v_emp int:=0;
BEGIN
SELECT count(*) into v_emp FROM dba_tables;
if v_emp = 0 then
EXECUTE IMMEDIATE 'create table EMPLOYEE ( ID NUMBER(3), NAME VARCHAR2(30) NOT NULL)';
end if;
END;
but give me an error 00103 because not find table
Just execute the create and watch the exception if thrown. Oracle would never replace the DDL of a table.
declare
error_code NUMBER;
begin
EXECUTE IMMEDIATE 'CREATE TABLE EMPLOYEE(AGE INT)';
exception
when others then
error_code := SQLCODE;
if(error_code = -955)
then
dbms_output.put_line('Table exists already!');
else
dbms_output.put_line('Unknown error : '||SQLERRM);
end if;
end;
You can run this for example:
if (select count(*) from all_tables where table_name = 'yourTable')>0 then
-- table exists
else
-- table doesn't exist
end if;
You should try following,
declare
nCount NUMBER;
v_sql LONG;
begin
SELECT count(*) into nCount FROM dba_tables where table_name = 'EMPLOYEE';
IF(nCount <= 0)
THEN
v_sql:='
create table EMPLOYEE
(
ID NUMBER(3),
NAME VARCHAR2(30) NOT NULL
)';
execute immediate v_sql;
END IF;
end;

PL/SQL: ORA-00904: : invalid identifier

I am running the following SP but getting the error c1.pyid is invalid identifier. I am trying to use two different query results from one cursor. If there is any other way of using IF-else clause in a cursor, i am open to that too.
CREATE OR REPLACE
PROCEDURE FIX_DOCUMENT_RECORDS ( i_flag in varchar)
AS
Op_ID VARCHAR(8);
Op_Name VARCHAR(32);
skill VARCHAR(32);
temp_count VARCHAR(8);
temp_status VARCHAR(8):='Submitted';
QRYSTR VARCHAR2(400);
TYPE REF_CUR IS REF CURSOR;
c1 REF_CUR;
BEGIN
IF (i_flag='1') THEN
QRYSTR:='SELECT *
FROM dims_doc_master
WHERE concat_prod_id IS NULL
OR documenttypeid IS NULL
AND (pystatuswork = temp_status);';
ELSE
QRYSTR:='SELECT *
FROM dims_doc_master
WHERE (documentimageid IS NULL
AND p8id IS NULL)
AND (pystatuswork = temp_status);';
END IF;
open c1 FOR QRYSTR;
LOOP
BEGIN
DBMS_OUTPUT.PUT_LINE('loop begin');
UPDATE DIMS_DOC_MASTER
SET pystatuswork ='Cancelled',
documentstatus ='Cancelled',
cancellationdate='31-JAN-14',
cancelledbysid = c1.pxcreateoperator,
cancelreason ='Cancelled due to corruption.'
WHERE pyid =c1.pyid;
DBMS_OUTPUT.PUT_LINE('After updation'||c1.pyid );
--Begin PC_DOCUMENT UPDATION
UPDATE PC_DOCUMENT
SET pystatuswork ='Cancelled',
cancellationdate='31-JAN-14'
WHERE pyid =c1.pyid;
--Begin insert into History
--Select Operator name and ID
SELECT skill
INTO skill
FROM operator_map_skill
WHERE pyuseridentifier=c1.pxcreateoperator
AND rownum =1;
INSERT
INTO DIMS_DOC_HIST
(
DIMS_DOC_ID,
DOC_CHG_USR,
DOC_CHG_DT,
DOC_NEW_STS,
DOC_CHG_CMNT,
CRE_TS,
ROLE,
RSN_DESC,
TARGETROLE,
DOC_CHG_USR_ID,
DOC_ASG_USR_ID,
DOC_ASG_USR,
PREVSTATUS,
PREVSTATUSDT,
ASSIGNEDTODT,
TODISPLAY,
ACTIVITY_NAME
)
VALUES
(
c1.pyid,
'DIMS',
systimestamp,
'Cancelled',
'Cancelled due to corruption',
'31-JAN-14',
skill,
NULL,
skill,
c1.pxcreateoperator,
c1.pxcreateoperator,
c1.pxcreateopname,
'Submitted',
NULL,
systimestamp,
'Y',
'Updation through Script'
);
dbms_output.put_line
(
'Document ID= '||c1.pyid
)
;
SELECT COUNT(*)
INTO temp_count
FROM PC_ASSIGN_WORKBASKET
WHERE pxrefobjectinsname=c1.pyid;
IF(temp_count IS NOT NULL) THEN
DELETE FROM PC_ASSIGN_WORKBASKET WHERE pxrefobjectinsname=c1.pyid;
ELSE
DELETE FROM PC_ASSIGN_WORKLIST WHERE pxrefobjectinsname=c1.pyid;
END IF;
COMMIT;
END;
END LOOP;
CLOSE c1;
END;
You seem confusing cursor and fetched row.
In your current procedure: you open a cursor, do a loop (which looks to be endless since there is no EXIT statement), and after the loop you close the cursor (but it looks it will never happen)
To fetch results from a cursor, do the following:
CREATE OR REPLACE PROCEDURE ...
...
c1 REF_CUR;
ddm_record dims_doc_master%rowtype;
BEGIN
...
OPEN c1;
LOOP
FETCH c1 INTO ddm_record;
EXIT WHEN c1%NOTFOUND;
...
DBMS_OUTPUT.PUT_LINE('Document ID= ' || ddm_record.pyid); -- not c1.pyid
END LOOP;
CLOSE c1;
END;
/
Inspired from examples here: http://plsql-tutorial.com/plsql-explicit-cursors.htm
Try embedding the flag in your where clause:
open c1 FOR
SELECT *
FROM dims_doc_master
WHERE (i_flag='1' AND
(concat_prod_id IS NULL
OR documenttypeid IS NULL
AND (pystatuswork = temp_status))
OR (i_flag<>'1' AND
(documentimageid IS NULL
AND p8id IS NULL)
AND (pystatuswork = temp_status));
The logic can probably be simplified but logically that would work.

IF else condition in sql stored procedure

I'm trying to compile the stored procedure:
create
procedure checkFroud2(code IN varchar2, p_recordset OUT SYS_REFCURSOR)
AS
BEGIN
OPEN p_recordset FOR
if code='C' then
select * from emp
//dbms_output.putline('this is if block')
else if code='F' then
dbms_output.putline('this is else block')
else
dbms_output.putline('last else')
end if;
end checkFroud2;
but this is showing compile time errors. Can anybody suggest where the problem is?
CREATE
PROCEDURE checkFroud2(
code IN VARCHAR2,
p_recordset OUT SYS_REFCURSOR)
AS
BEGIN
IF code='C' THEN
dbms_output.put_line('this is if block');
OPEN p_recordset FOR
SELECT * FROM emp;
ELSIF code='F' THEN
--you can open p_recordset with dummy as
/*open p_recordset for select * from dual where 1 = 0; */
dbms_output.put_line('this is else block');
ELSE
/*open p_recordset for select * from dual where 1 = 0; */
dbms_output.put_line('last else');
END IF;
END checkFroud2;
/
var o refcursor;
BEGIN
CHECKfroud2
('C',:o);
END;
/
PRINT O;
The correct code is as follows:
create procedure checkFroud2(code IN varchar2, p_recordset OUT SYS_REFCURSOR)
AS
BEGIN
OPEN p_recordset FOR
if code='C' then
select * from emp
//dbms_output.putline('this is if block');
elsif code='F' then
dbms_output.putline('this is else block');
else
dbms_output.putline('last else');
end if;
end checkFroud2;
ELSE IF doesn't exist use ELSIF, also remove // before dbms_output.putline('this is if block').
This is an example in oracle 11g
CREATE OR REPLACE PROCEDURE PROC_EMP_CHECK
(
EMPNO1 IN NUMBER
, EMPNO2 IN NUMBER
)
AS
EMPONE_NOT_EXISTS EXCEPTION;
EMPTWO_NOT_EXISTS EXCEPTION;
BOTHEMP_NOT_EXISTS EXCEPTION;
EMPCOUNT1 NUMBER;
EMPCOUNT2 NUMBER;
BEGIN
SELECT COUNT(1) INTO EMPCOUNT1 FROM EMPLOYEES WHERE EMPLOYEE_ID=EMPNO1;
SELECT COUNT(1) INTO EMPCOUNT2 FROM EMPLOYEES WHERE EMPLOYEE_ID=EMPNO2;
BEGIN
IF( EMPCOUNT1=0 AND EMPCOUNT2=0)THEN
RAISE BOTHEMP_NOT_EXISTS;
ELSIF ( EMPCOUNT1=0) THEN
RAISE EMPONE_NOT_EXISTS;
ELSIF ( EMPCOUNT2=0) THEN
RAISE BOTHEMP_NOT_EXISTS;
dbms_output.put_line('ELSE BLOCK');
END IF;
END;
EXCEPTION
WHEN EMPONE_NOT_EXISTS THEN
dbms_output.put_line('EMP One not exit');
WHEN EMPTWO_NOT_EXISTS THEN
dbms_output.put_line('EMP two not exit');
WHEN BOTHEMP_NOT_EXISTS THEN
dbms_output.put_line('both not exit');
WHEN OTHERS THEN
dbms_output.put_line(SQLERRM);
END PROC_EMP_CHECK;
Use ELSIF instead of ELSE IF. By using ELSE IF you're opening up a new nested IF-block, which you're not closing.
Couple of errors:
1. Open record set for ??? For what??
2. ELSIF and no ELSE IF
3. where is ;
CREATE PROCEDURE CHECKFROUD2 ( CODE IN VARCHAR2,
P_RECORDSET OUT SYS_REFCURSOR )
AS
BEGIN
OPEN P_RECORDSET FOR SELECT * FROM DUAL;
IF CODE = 'C'
THEN
SELECT * FROM EMP;
ELSIF CODE = 'F'
THEN
DBMS_OUTPUT.PUTLINE ( 'this is else block' );
ELSE
DBMS_OUTPUT.PUTLINE ( 'last else' );
END IF;
END CHECKFROUD2;