Subquery In if Statement (plsql) - oracle

I want to find if p_param2 is in subquery then do some operations according to this result. This subquery returns more than 1 row.
if p_param1 = 1
and p_param2 in (select code from x_table where code is not null) then
--..Some operations..
end if;
But I get PLS-00405 error. How can write this code effectively?

You need to get the needed value before IF..THEN statement within a seperate SQL query, while the current case is not possible. Try such a method which uses COUNT() aggregation without need of exception handling :
DECLARE
p_param1 ...
p_param2 ...
p_exists INT;
BEGIN
SELECT SIGN( COUNT(*) )
INTO p_exists
FROM x_table
WHERE code IS NOT NULL
AND code = p_param2;
IF p_param1 = 1 AND p_exists = 1 THEN
-- some operations
END IF;
END;
/

Declare a var v_dummy number. Then:
begin
select 1
into v_dummy
from x_table
where code = p_param2;
exception
when no_data_found then
v_dummy := 0;
end;
if p_param1 = 1 and v_dummy = 1 then
.
.
.
end if;
If x_table.code can contain duplicate values, you have to decide what to do when more than one occurrence of p_param2 is found.

Related

NO DATA FOUND oracle using cursor

I have been searching online using different solution suggestion to handle no data in this code but to no avail. how can I handle the exception if no data is found. How can I solve this problem. I am not an expert in oracle though!
DECLARE
nCheckOption INT;
no_data_found EXCEPTION;
CURSOR TYPE_cursor IS
SELECT
D_NAL_REF.TRANS
, D_NAL_REF.INJ
, D_NAL_REF.REF
FROM D_NAL_REF D_NAL_REF
WHERE D_NAL_REF.REF IN
(SELECT AG_REF.REF
FROM AG_REF A_REF
WHERE A_REF.DESCEND_REF = 10
);
BEGIN
FOR rec IN TYPE_cursor
LOOP
nCheckOption := 0;
SELECT 1
INTO nCheckOption
FROM PERSON_TYPE WHERE TRANS = rec.TRANS AND INJ = rec.INJ;
IF nCheckOption = 1 THEN
UPDATE PERSON_TYPE
SET PERSON_TYPE.TYPE = rec.REF
WHERE TRANS = rec.TRANS
AND PERSON_TYPE.INJ = rec.INJ;
END IF;
EXCEPTION
WHEN no_data_found
THEN
DBMS_OUTPUT.PUT_LINE ('Trapped the error!?');
END LOOP;
END;
/
Rewrite your code to eliminate the inner SELECT, which is the only place in your code where I can see that a NO_DATA_FOUND exception could possibly be raised:
BEGIN
FOR rec IN (SELECT d.TRANS,
d.INJ,
d.REF
FROM D_NAL_REF d
WHERE d.REF IN (SELECT a.REF
FROM AG_REF a
WHERE a.DESCEND_REF = 10) AND
(d.TRANS, d.INJ) IN (SELECT DISTINCT TRANS, INJ
FROM PERSON_TYPE))
LOOP
UPDATE PERSON_TYPE
SET TYPE = rec.REF
WHERE TRANS = rec.TRANS AND
INJ = rec.INJ;
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('Trapped the error!?');
END;
I think you need to find if cursor contains any record or not. If cursor is empty then it must return that error message written in exception block.
Or you want to print error message if update statement do not find any record to update.
Here is the pseudo code.
Declare
ncheckoption number := 0;
Cursor type_cursor is ....
Begin
For rec in type_cursor loop
ncheckoption := ncheckoption + 1;
Update ...
If sql%rowcount = 0 then
Dbms_output.put_line('error message, if you want here in case no record found in table to update');
-- loop will continue
-- if you want loop to break then issue exit statement here
End if;
End loop;
If ncheckoption = 0 then
Dbms_output.put_line('error message you want to print in case cursor is empty');
End if;
End;
/
Cheers!!

Oracle cannot perform dml operations cant be called inside query

CREATE OR REPLACE FUNCTION cash_out_ticket(party_id IN softdev.casino_users.party_id%TYPE ,session_id IN softdev.bus_session.session_id%TYPE
) RETURN NUMBER AS ret_val NUMBER;
P_EXCHANGE_BET_CREDITS softdev.COUNTRY.EXCHANGE_BET_CREDITS%type;
P_EXCHANGE_VALUE softdev.COUNTRY.EXCHANGE_VALUE%type;
p_reserved_funds softdev.casino_users.credits%type;
p_session_id softdev.bus_session.session_id%type;
p_session_close softdev.bus_session.session_close%type;
ticket_closed exception;
CURSOR cur_tkt_sess (party_id IN softdev.casino_users.party_id%TYPE,session_id IN softdev.bus_session.session_id%TYPE)
IS
SELECT bs.session_id
,tii.status
,ROW_NUMBER() OVER (PARTITION BY bs.session_id ORDER BY status ASC) rn
,NVL(TO_CHAR(bs.started, 'DD.MM.YYYY HH24:MI'), 'Live') started
,bs.bet bet
-- ,bs.player_win * P_EXCHANGE_BET_CREDITS / P_EXCHANGE_VALUE AS possible_win
-- ,bs.house_win AS odds
,tii.time_p
,tii.live_prematch
,cash_out(bet) cash_out
FROM bus_session bs
,ticket_items tii
WHERE bs.session_id = tii.bus_session_session_id
AND bs.session_type = 'TICKET SESSION'
AND bs.party_id = cur_tkt_sess.party_id
AND bs.session_id = cur_tkt_sess.session_id
AND NVL(bs.session_close, 'N') = 'N';
rec_tkt_sess cur_tkt_sess%ROWTYPE;
BEGIN
CHAGE_CREDITS (party_id, P_EXCHANGE_BET_CREDITS, P_EXCHANGE_VALUE);
OPEN cur_tkt_sess(cash_out_ticket.party_id, cash_out_ticket.session_id);
FETCH cur_tkt_sess
INTO rec_tkt_sess;
IF(cur_tkt_sess%FOUND) THEN
IF(
(TO_DATE(rec_tkt_sess.started,'DD.MM.YYYY HH24:MI:SS') +1 <=SYSDATE) -- je li tiket stariji od 24h
OR
(rec_tkt_sess.live_prematch != '0') --je li live (1 live , 0 not live)
OR
(rec_tkt_sess.time_p <SYSDATE) -- je li utakmice počela
)
THEN
ret_val := 0;
ELSE
ret_val := rec_tkt_sess.cash_out* P_EXCHANGE_BET_CREDITS / P_EXCHANGE_VALUE;
play_beting.end_of_ticket(cash_out_ticket.session_id ,rec_tkt_sess.cash_out* P_EXCHANGE_BET_CREDITS / P_EXCHANGE_VALUE ,cash_out_ticket.party_id );
--this procedure do updates , does not return anything. And it need to be run when conditions are fulfilled.
END IF;
ELSE
ret_val := -1;
END IF;
RETURN(ret_val);
END cash_out_ticket;
I have this function cash_out_ticket which goes through cursor and then cursors items runs through IF statement if conditions are fulfilled it need to return cash_out and run procedure end_of_ticket.
But when i call cash_out_ticket from dual i get error that i cannot perform dml operation inside query .
In my case dml operations are inside of end_of_ticket. It doesnt return anything just do some updates from IN parameters.
Is there way to call end_of_ticket when conditions from if are right?
As the error says, you can't call your function from a query because of the DML (insert/update/delete) in the procedure it calls. So you can't do:
select cash_out_ticket(42, 123) from dual;
ORA-14551: cannot perform a DML operation inside a query
You can call it from a PL/SQL context, e.g. in an anonymous block:
declare
ret_val number;
begin
ret_val := cash_out_ticket(party_id => 42 ,session_id => 123);
-- do something with ret_val
end;
/
Depending on where and how you had planned to call it you could use a bind variable to retrieve the return value.

Retrieving multiple attributes in SELECT

In PL/SQL function, I am trying to write a function with following code:
CREATE OR REPLACE FUNCTION Lib_func(id number,dateToday date)
RETURN number IS retVal number(1);
myBorrower number;
myBook number;
BEGIN
SELECT P.book_id INTO myBook, P.request_id INTO myBorrower
FROM My_requests P
WHERE P.book_id = book_id AND ROWNUM <=1;
//some if condition which updates value of retVal
RETURN retVal;
END;
/
problem is that this results in error when I compile. If I remove the second thing (i.e. P.request_id INTO myBorrower) then error is removed.
Can I not get both things selected in a single query ?
The syntax for selecting multiple variables is :
SELECT P.book_id , P.request_id
INTO myBook,myBorrower
FROM My_requests P
WHERE P.book_id = book_id AND ROWNUM <=1;

ORA-01007 "variable not in select list" from dbms_sql.column_value call

I am trying to use dynamic SQL to sample all the data in a schema with a pattern:
DECLARE
xsql varchar2(5000);
c NUMBER;
d NUMBER;
col_cnt INTEGER;
f BOOLEAN;
rec_tab DBMS_SQL.DESC_TAB;
col_num NUMBER;
varvar varchar2(500);
PROCEDURE print_rec(rec in DBMS_SQL.DESC_REC) IS
BEGIN
DBMS_OUTPUT.ENABLE(1000000);
DBMS_OUTPUT.NEW_LINE;
DBMS_OUTPUT.PUT_LINE('col_type = '
|| rec.col_type);
DBMS_OUTPUT.PUT_LINE('col_maxlen = '
|| rec.col_max_len);
DBMS_OUTPUT.PUT_LINE('col_name = '
|| rec.col_name);
DBMS_OUTPUT.PUT_LINE('col_name_len = '
|| rec.col_name_len);
DBMS_OUTPUT.PUT_LINE('col_schema_name = '
|| rec.col_schema_name);
DBMS_OUTPUT.PUT_LINE('col_schema_name_len = '
|| rec.col_schema_name_len);
DBMS_OUTPUT.PUT_LINE('col_precision = '
|| rec.col_precision);
DBMS_OUTPUT.PUT_LINE('col_scale = '
|| rec.col_scale);
DBMS_OUTPUT.PUT('col_null_ok = ');
IF (rec.col_null_ok) THEN
DBMS_OUTPUT.PUT_LINE('true');
ELSE
DBMS_OUTPUT.PUT_LINE('false');
END IF;
END;
BEGIN
c := DBMS_SQL.OPEN_CURSOR;
xsql:='
WITH got_r_num AS
(
SELECT e.* -- or whatever columns you want
, ROW_NUMBER () OVER (ORDER BY dbms_random.value) AS r_num
FROM dba_tab_columns e
)
SELECT * -- or list all columns except r_num
FROM got_r_num
WHERE r_num <= 10';
DBMS_SQL.PARSE(c, xsql, DBMS_SQL.NATIVE);
d := DBMS_SQL.EXECUTE(c);
DBMS_SQL.DESCRIBE_COLUMNS(c, col_cnt, rec_tab);
LOOP
IF DBMS_SQL.FETCH_ROWS(c)>0 THEN
NULL;
-- get column values of the row
DBMS_SQL.COLUMN_VALUE(c, 2, varvar);
--dbms_output.put_line('varvar=');
--DBMS_SQL.COLUMN_VALUE(source_cursor, 2, name_var);
--DBMS_SQL.COLUMN_VALUE(source_cursor, 3, birthdate_var);
-- Bind the row into the cursor that inserts into the destination table. You
-- could alter this example to require the use of dynamic SQL by inserting an
-- if condition before the bind.
--DBMS_SQL.BIND_VARIABLE(destination_cursor, ':id_bind', id_var);
--DBMS_SQL.BIND_VARIABLE(destination_cursor, ':name_bind', name_var);
--DBMS_SQL.BIND_VARIABLE(destination_cursor, ':birthdate_bind',
--birthdate_var);
--ignore := DBMS_SQL.EXECUTE(destination_cursor);
--ELSE
-- No more rows to copy:
--EXIT;
END IF;
END LOOP;
--EXIT WHEN d != 10;
--END LOOP;
col_num := rec_tab.first;
IF (col_num IS NOT NULL) THEN
LOOP
print_rec(rec_tab(col_num));
col_num := rec_tab.next(col_num);
EXIT WHEN (col_num IS NULL);
END LOOP;
END IF;
DBMS_SQL.CLOSE_CURSOR(c);
END;
/
When I run that it gives me this error from the line with the dbms_sql.column_value call:
ORA-01007: variable not in select list
If I comment out that dbms_sql.column_value call it still errors but now with:
ORA-01002: fetch out of sequence
What am I doing wrong?
You have two problems in the code you posted. Firstly you have skipped part of the execution flow because you haven't called the DEFINE_COLUMN procedure. That is what is causing the ORA-01007 error, as the dynamic SQL processing hasn't been told about the select list columns via that call. For your current code you only need to define column 2, but assuming you will actually want to refer to the others you can define them in a loop. To treat them all as string for display you could do:
...
DBMS_SQL.PARSE(c, xsql, DBMS_SQL.NATIVE);
d := DBMS_SQL.EXECUTE(c);
DBMS_SQL.DESCRIBE_COLUMNS(c, col_cnt, rec_tab);
FOR i IN 1..col_cnt
LOOP
-- dbms_output.put_line('col_name is ' || rec_tab(i).col_name);
DBMS_SQL.DEFINE_COLUMN(c, i, varvar, 500);
END LOOP;
LOOP
IF DBMS_SQL.FETCH_ROWS(c)>0 THEN
...
If you want to do anything that needs to treat the variables as the right types you could have a local variable of each type and use the data type from the rec_tab information you already have from describe_columns to use the appropriately typed variable for each column.
The second problem, which you were hitting when you commented the column_value call, is still there once that definbe issue has been fixed. Your loop doesn't ever exit, so after you fetch the last row from the cursor you do a further invalid fetch, which throws ORA-01002. You have the code to avoid that already but it's commented out:
...
LOOP
IF DBMS_SQL.FETCH_ROWS(c)>0 THEN
-- get column values of the row
DBMS_SQL.COLUMN_VALUE(c, 2, varvar);
...
ELSE
-- No more rows to copy:
EXIT;
END IF;
END LOOP;
...
With those two changes your code runs, and dumps the view structure:
PL/SQL procedure successfully completed.
col_type = 1
col_maxlen = 30
col_name = OWNER
col_name_len = 5
col_schema_name =
col_schema_name_len = 0
col_precision = 0
col_scale = 0
col_null_ok = false
col_type = 1
col_maxlen = 30
col_name = TABLE_NAME
...
To those who find this question when accessing Oracle through ODP.NET, as I did:
We started getting this error whenever we would add column to an existing table in our application. I'm not sure what all the conditions were to make it fail, but ours were:
Run a SELECT * FROM "table".
Include a ROWNUM restriction in the WHERE clause (WHERE ROWNUM < 10).
Run that through the ODP.NET dataReader.GetSchemaTable() call.
Running unrestricted queries or running queries directly on Oracle SQL Developer did not seem to cause the error.
I've hit some pretty weird stuff in the past with Oracle connection pooling, so I eventually thought that could be the problem. The solution was to restart the web service to force all the connections to be fully dropped and recreated.
The theory is that the ODP.NET connection from the connection pool still had no idea the column existed on the table, but the column was returned by the database.

why i am getting no data found error?

to a void this error i just make to variable so if there record return then do else do
but i am still getting this error anyone can help me to get out of that ?
thats worked at first query but not the query on line 35
can i use sql%rowcount instead ?
declare
cust_id bmh.info.CUSTOMER_ID#prod%type; --get the id of sp number
num number; -- count of records in rated_rejectes_calls_cursor
num1 number; -- count of records in rated_rejectes_calls_cursor
V_CUST_INFO_CUSTOMER_ID FI_MASAAD.FEB_PRD_14_VIEW.CUST_INFO_CUSTOMER_ID#rtx%type;
V_INITIAL_START_TIME_TIMESTAMP FI_MASAAD.FEB_PRD_14_VIEW.INITIAL_START_TIME_TIMESTAMP#rtx%type;
cursor rated_rejectes_calls_cursor is
select S_P_NUM,CALL_START_TIME
from fi_sdine.rejected_calls_87#prod
where UPPER (STATUS)='RATED';
begin
for rated_rejectes_calls_rec in rated_rejectes_calls_cursor
loop
select count(*) into num from bmh.info#prod where dn_num=rated_rejectes_calls_rec.S_P_NUM;
if num <>0 then
select CUSTOMER_ID into cust_id from bmh.info#prod where dn_num=rated_rejectes_calls_rec.S_P_NUM;
dbms_output.put_line('SP number, '||rated_rejectes_calls_rec.S_P_NUM||' ID is, '||cust_id||' and call start time, '||rated_rejectes_calls_rec.CALL_START_TIME);
select count(*) into num1
from FI_MASAAD.MAR_14_VIEW#rtx a
where CUST_INFO_CUSTOMER_ID =cust_id
and INITIAL_START_TIME_TIMESTAMP=rated_rejectes_calls_rec.CALL_START_TIME;
elsif num1 <> 0 then
select CUST_INFO_CUSTOMER_ID, INITIAL_START_TIME_TIMESTAMP into V_CUST_INFO_CUSTOMER_ID,V_INITIAL_START_TIME_TIMESTAMP
from FI_MASAAD.MAR_14_VIEW#rtx a
where CUST_INFO_CUSTOMER_ID =cust_id
and INITIAL_START_TIME_TIMESTAMP=rated_rejectes_calls_rec.CALL_START_TIME
group by CUST_INFO_CUSTOMER_ID,INITIAL_START_TIME_TIMESTAMP;
elsif num1 =0 then
dbms_output.put_line('tickets not found, '||rated_rejectes_calls_rec.S_P_NUM);
elsif num=0 then
dbms_output.put_line('SP number ID not found, '||rated_rejectes_calls_rec.S_P_NUM);
end if;
end loop;
end;
thank you all in advance
Use nested begin blocks..
BEGIN
--statements
BEGIN
select CUSTOMER_ID into cust_id from bmh.info#prod where dn_num=rated_rejectes_calls_rec.S_P_NUM;
EXCEPTION WHEN NO_DATA_FOUND THEN
--Handle Exception for No Data here
END;
EXCEPTION WHEN OTHERS THEN
-- Final Exceptions go here
END;
/

Resources