I am new to PL/SQL and experimenting with CURSOR. I desire to verify an insertion procedure so I wrote another procedure to do so.
CREATE OR REPLACE PROCEDURE verify_insert
IS
CURSOR map_cur IS
SELECT Page_ID_NBR, Page_Type, Page_Dcpn FROM SSC_Page_Map;
map_rec map_cur%ROWTYPE;
BEGIN
OPEN map_cur;
FOR map_rec in map_cur
LOOP
DBMS_OUTPUT.PUT_LINE('ID: ' || map_cur.Page_ID_NBR || ' ' || 'Type' || map_cur.Page_Type || ' ' || 'Description' || map_cur.Page_Dcpn);
END LOOP;
CLOSE map_cur;
END;
SHOW ERRORS PROCEDURE verify_insert;
I am getting the following message
[Warning] ORA-24344: success with compilation error
19/44 PLS-00225: subprogram or cursor 'MAP_CUR' reference is out of scope
19/5 PL/SQL: Statement ignored
(47: 0): Warning: compiled but with compilation errors
I also see
Errors for PROCEDURE VERIFY_INSERT
LINE/COL ERROR
-------- -----------------------------------------------------------------
19/44 PLS-00225: subprogram or cursor 'MAP_CUR' reference is out of sco
19/5 PL/SQL: Statement ignored
As I wrote, I am new and trying to cobble together knowledge of PL/SQL from Oracle PL/SQL Programming (Feuerstein) and the net. Coming together but not as fast as I want.
Your loop is fetching a row from the cursor into the record type. Inside the loop, you'd want to read the data from the record type. In your dbms_output.put_line call, you'd want to reference the record not the cursor.
DBMS_OUTPUT.PUT_LINE('ID: ' || map_rec.Page_ID_NBR ||
' ' || 'Type' || map_rec.Page_Type ||
' ' || 'Description' || map_rec.Page_Dcpn);
Related
Trying to dynamically generate and execute a PL/SQL statement. It doesn't return results, but executing okay. What I am trying is to get the table name from the schema in first statement (got it right!), and append that to a select statement, and then execute it to return the table results.
DECLARE
LATEST_TABLE VARCHAR2(256);
PostalCode ADM.POSTAL_CODE_201801%ROWTYPE;
BEGIN
SELECT TO_CHAR(max(table_name)) INTO LATEST_TABLE FROM all_tables WHERE owner = 'ADM' AND table_name LIKE 'POSTAL_CODE_%';
LATEST_TABLE := 'begin Select POSTALCODE,LONGITUDE,LATITUDE,MUNICIPALITY_FULL_NAME,LOCAL_NAME,SZONE_NAME,ZONE_NAME,RHA_CODE,RHA_NAME,URBAN,ZONE_RURAL from ADM.'||LATEST_TABLE||' ;end;';
execute immediate LATEST_TABLE into PostalCode;
Exception
When others then
Null;
END;
Why am I not getting any results? Adding
dbms_output.put_line(PostalCode.LONGITUDE || PostalCode.LATITUDE); after execute immediate is also not generating results!
I see a couple of issues here; your code is something like:
declare
vSQL varchar2(1000);
vTabName varchar2(30);
vResult number;
begin
select table_name into vTabName from user_tables;
vSQL := 'begin select a from ' || vTabName || '; end;';
execute immediate vSQL into vResult;
dbms_output.put_line('REsult: ' || vResult);
exception
when others then
null
end;
If you run this, you see nothing, because the dynamic part gives error, but the (dangerous) exception handling hides it; if you would edit the null; into something like
dbms_output.put_line('Error: ' || sqlerrm);
you would get:
Error: ORA-06550: line 1, column 7:
PLS-00428: an INTO clause is expected in this SELECT statement
In fact you dynamic code is like
begin select a from someTable; end;
and this gives error.
A way to do what you need could be:
...
vSQL := 'select a from ' || vTabName;
execute immediate vSQL into vResult;
...
I have the following code:
declare
y pls_integer := 0;
v_msg varchar2(4000);
plsql varchar(4000);
begin
if not apex_collection.collection_exists(p_collection_name=>'P16_COLLECTION') then
wwv_flow.debug('No Apex collection found!');
else
for x in (select * from apex_collections where collection_name = 'P16_COLLECTION' and seq_id > 1 order by seq_id)
loop
y := y+1;
FOR i IN 1..25
LOOP
plsql := 'begin apex_collection.update_member_attribute (p_collection_name=> ''P16_COLLECTION'', p_seq=>' || TO_CHAR(x.seq_id) || ',p_attr_number =>' || TO_CHAR(i) || ',p_attr_value=>wwv_flow.g_f' || TO_CHAR(i, 'FM00') || '(' || TO_CHAR(y) || ')); end;';
wwv_flow.debug(plsql);
EXECUTE IMMEDIATE plsql;
END LOOP;
end loop;
end if;
exception when others then
v_msg := ''||sqlerrm;
wwv_flow.debug('ERR: '||v_msg);
end;
This code is very similar to the one proposed here, but I loop through 25 columns. The issue with Oracle Apex is the max number of chars PL/SQL is allowed to have, so I am unable to just write 25 update_member_attribute - calls.
But instead of a it excecuting I get an error no data found.
I triple checked that the collection P16_COLLECTION exists.
The issue with Oracle Apex is the max number of chars PL/SQL is allowed to have
I'm not sure I understood this statement. It is PL/SQL you use. You declared a local PLSQL variable as VARCHAR2(4000). Why didn't you specify its max allowed size, 32767? Would that help?
Furthermore, saying that you got NO-DATA-FOUND exception: are you sure that this piece of code raised it? Because, there's no SELECT statement in there ... the one you used in a cursor FOR loop can't raise NO-DATA-FOUND; UPDATE either. Therefore, it must be something else, I presume.
Enable DEBUG, run the page and - when you get the error - view debug results and locate the culprit.
I have table named "players" like this
Name Country
---------- ------------
Sachin India
Ponting Australia
I have written a PL/SQL Procedure to execute it by giving "name" as parameter.
Here is the code-
CREATE OR REPLACE PROCEDURE NEW_TEST ( player IN players.name%type, place IN players.country%type ) IS
countri players.country%type;
BEGIN
SELECT country into countri from players where name = player;
END;
DECLARE
player players.name%type;
place players.country%type;
CURSOR cu_new0 is
SELECT name, country from players where name=player;
BEGIN
player:='Sachin' ;
FOR pl_all in cu_new0
LOOP
NEW_TEST (player, place);
dbms_output.put_line ('The player ' || player || ' play for ' || pl_all.country);
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('No such player!');
WHEN OTHERS THEN
dbms_output.put_line('Error!');
END;
Now when I am putting player:='Sachin' it is giving output but when I am giving player:= 'Sachin1' is not showing any output and more importantly it is not even going to exception of 'NO_DATA_FoUND'. Can you please help me in this regard. Thanx
If you code a loop, Oracle does not throw an exception if no data is returned (just as it doesn't throw a TOO_MANY_ROWS exception if more than one row is returned).
Your one of the select clause is not handling exception; you are consuming exception in that code.
Your Original Code:
BEGIN
SELECT country into countri from players where name = player;
END;
Modify with below code--
BEGIN
SELECT country into countri from players where name = player;
exception when no_data_found then
raise_application_error(......);
END;
DECLARE
player players.name%type;
place players.country%type;
CURSOR cu_new0 is
SELECT name, country from players where name=player;
type l_cu_new0 is table of cu_new0%rowtype;
v_cu_new0 l_cu_new0;
BEGIN
player:='Sachin' ;
open cu_new0;
fetch cu_new0 bulk collect into v_cu_new0;
close cu_new0;
if v_cu_new0.count = 0 then
raise NO_DATA_FOUND;
end;
FOR i in v_cu_new0.first .. v_cu_new0.last
LOOP
...
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('No such player!');
WHEN OTHERS THEN
dbms_output.put_line('Error!');
END;
There are your cursor is NULL. Because;
Temp code block :
select name
,country
from players
where name = :player;
Run code block :
select name
,country
from players
where name = 'Schin1';
Run code block return NULL and your cursor is have NULL value.
Then your for loop code block is not work.
You can solve this problem such as ;
CURSOR cu_new0 is
SELECT name, country from players;
Hi #Warrior92 for edit,
There are maybe you can try it ;
for pl_all in cu_new0 loop
new_test(player
,place);
if pl_all.name = player then
dbms_output.put_line('The player ' || player || ' play for ' || pl_all.country);
end if;
end loop;
If you really want to use a cursor, the for loop and an exception, you can try the following code:
DECLARE
-- create table type of players
TYPE t_players_tab IS TABLE OF players%ROWTYPE;
-- declare variable / array which will contain the result of cursor's select
l_players_arr t_players_tab := NEW t_players_tab();
CURSOR c_fetch_player IS
SELECT
*
FROM
players
WHERE
name = player;
-- declare exception which is to be caught within the EXCEPTION block
EXCEPTION e_player_not_found;
-- init the exception giving it the sqlcode -20001 (valid numbers for custom exceptions are in range from -20000 to -20999)
PRAGMA EXCEPTION_INIT(e_player_not_found, -20001);
BEGIN
-- fetch the cursor result into the array
OPEN c_fetch_player;
FETCH c_fetch_player BULK COLLECT INTO l_players_arr;
CLOSE c_fetch_player;
-- check if the array contains any results
IF l_players_arr.COUNT > 0 THEN
-- iterate through the rows in the array
FOR idx l_players_arr.FIRST .. l_players_arr.LAST
LOOP
dbms_output.put_line ('The player ' || player || ' play for ' || l_players_arr(idx).country);
END LOOP;
ELSE -- if the array has no rows, raise application arror with the same sqlcode as defined in EXCEPTION_INIT
raise_application_error(-20001,'Player ' || player || 'not found');
END IF;
EXCEPTION
-- catch the exception
WHEN e_player_not_found THEN
dbms_output.put_line(sqlcode || ': ' || sqlerrm);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_CALL_STACK);
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_STACK);
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
END;
/
Below is a plsql procedure which was written by someone else and I have asked to fix its compilation errors and run it right.
PROCEDURE DropMyTable IS
x number;
TYPE cur_typ IS REF CURSOR;
--type NAME_TBL is table of VARCHAR2(30);
--tab_Table NAME_TBL;
tab_Table VARCHAR2S(30);
stmt VARCHAR2(4096);
stmt2 VARCHAR2(4096);
outerCur cur_typ;
rows NATURAL := 1000;
TABLE_DOES_NOT_EXIST EXCEPTION;
PRAGMA EXCEPTION_INIT(TABLE_DOES_NOT_EXIST, -942);
BEGIN
stmt2 := 'select distinct G_Tab from G_SERVE where G_TYPE=''CAP''';
--Begin
OPEN outerCur FOR stmt2;
LOOP
FETCH outerCur BULK COLLECT INTO
tab_Table LIMIT rows;
EXIT WHEN tab_Table.COUNT = 0;
FOR i IN 1..tab_Table.COUNT LOOP
--------------------------------------------------------------------
-- Drop the tables in G_SERVE.G_TAB
DBMS_OUTPUT.PUT_LINE('*** Drop table: ' || tab_Table(i) || ' ***');
-- BEGIN
--First drop the optable
stmt := 'DROP TABLE ' || tab_Table(i) || '_OPTAB CASCADE CONSTRAINTS';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE stmt;
--drop the base table
stmt := 'DROP TABLE ' || tab_Table(i) || ' CASCADE CONSTRAINTS';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE stmt;
--drop the Package
stmt := 'DROP PACKAGE ' || tab_Table(i) || '_PKG';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE stmt;
EXCEPTION
-- When the table, optab and package doesn't exist,
-- ignore error "ORA-00942: table, optab or package does not exist".
WHEN TABLE_DOES_NOT_EXIST THEN
DBMS_OUTPUT.PUT_LINE('table, optab or package does not exist');
DBMS_OUTPUT.PUT_LINE(CHR(9));
--Re-raises any other errors.
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error!');
RAISE;
END;
END LOOP;
END LOOP;
--END;
END DropMyTable;
First up I have commented out 4th and 5th line of code from begging and changed it to what it looks like now ( 6th line from the top).
Other thing I have commented out 2 BEGIN keywords first commented out "BEGIN" can be seen after
stmt2 := 'select distinct gao_table from GAO_SERVICESIFACE where GAO_TYPE=''CAPABILITY''';
and the second "BEGIN" keyword has been commented out after the following line of code.
DBMS_OUTPUT.PUT_LINE('*** Drop table: ' || tab_Table(i) || ' ***');
Since I suspect that whoever has written this code put unnecessary "BEGIN" keyword (i apologize if I'm wrong as I'm not a plsql expert. But doing all the commenting out thing i got rid of so many errors).
But when I compile the above code I still get following 2 errors.
1)
ORA-06550: line 27, column 7:
PLS-00103: Encountered the symbol "EXCEPTION" when expecting one of the following:
;
( begin case declare end exit for goto if loop mod null
pragma raise return select update while with <an identifier>
<a double-quoted delimited-identifier> <a bind variable> <<
continue close current delete fetch lock insert open rollback
savepoint set sql execute commit forall merge pipe purge
2)
ORA-06550: line 38, column 9:
PLS-00103: Encountered the symbol "LOOP" when expecting one of the following:
;
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
You have commented out the BEGIN inside the inner loop but not its associated EXCEPTION and END. You need that begin. Also you cannot change an array to a scalar variable while the code still expects an array (references to tab_Table(i) etc.)
Decent indentation of code always makes it easier to follow:
PROCEDURE DropMyTable IS
x number;
TYPE cur_typ IS REF CURSOR;
type NAME_TBL is table of VARCHAR2(30);
tab_Table NAME_TBL;
--tab_Table VARCHAR2S(30);
stmt VARCHAR2(4096);
stmt2 VARCHAR2(4096);
outerCur cur_typ;
rows NATURAL := 1000;
TABLE_DOES_NOT_EXIST EXCEPTION;
PRAGMA EXCEPTION_INIT(TABLE_DOES_NOT_EXIST, -942);
BEGIN
stmt2 := 'select distinct G_Tab from G_SERVE where G_TYPE=''CAP''';
--Begin
OPEN outerCur FOR stmt2;
LOOP
FETCH outerCur BULK COLLECT INTO
tab_Table LIMIT rows;
EXIT WHEN tab_Table.COUNT = 0;
FOR i IN 1..tab_Table.COUNT LOOP
--------------------------------------------------------------------
-- Drop the tables in G_SERVE.G_TAB
DBMS_OUTPUT.PUT_LINE('*** Drop table: ' || tab_Table(i) || ' ***');
BEGIN
--First drop the optable
stmt := 'DROP TABLE ' || tab_Table(i) || '_OPTAB CASCADE CONSTRAINTS';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE stmt;
--drop the base table
stmt := 'DROP TABLE ' || tab_Table(i) || ' CASCADE CONSTRAINTS';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE stmt;
--drop the Package
stmt := 'DROP PACKAGE ' || tab_Table(i) || '_PKG';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE stmt;
EXCEPTION
-- When the table, optab and package doesn't exist,
-- ignore error "ORA-00942: table, optab or package does not exist".
WHEN TABLE_DOES_NOT_EXIST THEN
DBMS_OUTPUT.PUT_LINE('table, optab or package does not exist');
DBMS_OUTPUT.PUT_LINE(CHR(9));
--Re-raises any other errors.
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error!');
RAISE;
END;
END LOOP;
END LOOP;
--END;
END DropMyTable;
I have reinstated that BEGIN and restored the array. I don't know if there is anything else wrong.
Hello I exported database using datapump another schema so this synonyms must be in another new schema.
My old one is KTECH and new one is LTECH
DECLARE
strSynonyms_KTECH VARCHAR2(3000) := 'KTECH ';
strSynonyms_LTECH VARCHAR2(3000) := 'LTECH';
strCommand VARCHAR2(33865);
BEGIN
LOOP
FOR Synonym IN (SELECT * FROM ALL_SYNONYMS WHERE OWNER = strSynonyms_KTECH)
strCommand := 'CREATE OR REPLACE SYNONYM ' ||
Synonym.KTECH || '.' || Synonym.SYNONYM_NAME ||
' FOR ' || strSynonyms_LTECH || '.' ||
Synonym.TABLE_NAME;
EXECUTE IMMEDIATE strCommand;
END LOOP;
END;
I tried to run it but it shows me error.
you can export database synonyms from old schema as text file by using pl/sql or TOAD, then save the exported file as script, edit it then execute it on new schema.
by plsql developer:
by Toad: