I have written the code below to correct all table in my db.
Please review and correct it.
Declare
Name Varchar2(100);
A Number:=0;
Cursor C1 Is
Select Table_Name From Tabs;
Begin
Open C1;
Loop
A:=A+1;
Fetch C1 Into Name;
Exit When C1%Notfound;
Execute Immediate 'Create Or Replace View Tab||A
As
Select * From Name';
End Loop;
Close C1;
End
Please correct my Code
This forum is not a place to give people assigments, please ask questions about the issue you are running into and we are willing to help you. Please try doing a better job next time.
Your execute immediate string should be:
Execute Immediate
'Create Or Replace View Tab' ||A|| '
As
Select * From ' || Name;
and don't forget the ; after the final end
fixed your code:
Declare
Name Varchar2(100);
A Number:=0;
Cursor C1 Is
Select Table_Name From Tabs;
Begin
Open C1;
Loop
A:=A+1;
Fetch C1 Into Name;
Exit When C1%Notfound;
Execute Immediate 'Create Or Replace View Tab'||A||'
As
Select * From "'||Name||'"';
End Loop;
Close C1;
End;
/
But I would do something like this:
declare
procedure p_exec(pCMD in varchar2, pPrintOnly varchar2 default 'n') is
begin
if pPrintOnly='y' then
dbms_output.put_line(pCMD);
else
execute immediate pCMD;
dbms_output.put_line(pCMD);
end if;
end;
begin
for r in (Select rownum rn, Table_Name From Tabs) loop
p_exec(
utl_lms.format_message(
'Create Or Replace View Tab%s As Select * From "%s"'
, to_char(r.rn,'fm9999')
, r.table_name
)
-- ,'y' -- << uncomment to print commands only without execution
);
end loop;
end;
/
Related
I need to run below code on different environments and it works fine when table1 exists but when it does not exist then it throws error in cursor declaration that "table or view does not exist".
I am running this on Oracle.
Could you please help me in correcting this?
Thanks in advance.
DECLARE
CURSOR my_cursor IS (select "col1" from "table1");
name1 VARCHAR2(256);
tableCount NUMBER;
BEGIN
Select count(*) into tableCount from user_tab_cols where table_name = 'table1' and column_name = 'col2';
IF tableCount > 0 THEN
OPEN my_cursor;
LOOP
FETCH my_cursor into name1;
EXIT WHEN my_cursor%notfound;
-- Update or delete statement here
DBMS_OUTPUT.PUT_LINE('value is ' || name1);
END LOOP;
CLOSE my_cursor;
END IF;
END;
/
A CURSOR with a defined return type is strongly typed. Sys_refcursors are weakly typed. This means that any return type in a CURSOR must be valid. A SYS_REFCURSOR is more flexible and can be defined at a later time.
When setting a CURSOR in the declaration section, you must use a SQL statement that will execute properly. In this case, you are setting the CURSOR to select a column from a table that does not exist. The database execution will not reach the body of the code since it errors prior to exiting the declaration block.
To fix this, use a SYS_REFCURSOR with a dynamic sql query, as mentioned by Tejash above. This allows you to check to see if the table exists before setting the cursor. If the table exists, set the cursor to select from the specified table. If it doesn't, output a message saying that it does not exist.
Note that you can also use the SQL error codes, as shown in other answers. I prefer personally to handle business rules in the logic prior to the error occurring.
DECLARE
my_cursor sys_refcursor;
name1 VARCHAR2(256);
tableCount NUMBER;
BEGIN
Select count(*) into tableCount from user_tab_cols where table_name = 'table1' and column_name = 'col2';
IF tableCount > 0 THEN
OPEN my_cursor for 'select order_id from table1';
LOOP
FETCH my_cursor into name1;
EXIT WHEN my_cursor%notfound;
-- Update or delete statement here
DBMS_OUTPUT.PUT_LINE('value is ' || name1);
END LOOP;
CLOSE my_cursor;
else
dbms_output.put_line('Table does not exist');
END IF;
END;
http://docs.oracle.com/database/122/LNPLS/static-sql.htm#LNPLS568
You can use the exceptions and dynamic string for a cursor as follows:
DECLARE
MY_CURSOR SYS_REFCURSOR;
NAME1 VARCHAR2(256);
TABLECOUNT NUMBER;
BEGIN
OPEN MY_CURSOR FOR 'SELECT ACC_NR FROM ACCOUNT'; -- dynamic string for cursor
LOOP
FETCH MY_CURSOR INTO NAME1;
EXIT WHEN MY_CURSOR%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('value is ' || NAME1);
END LOOP;
CLOSE MY_CURSOR;
EXCEPTION -- exception handling using SQLCODE
WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_OUTPUT.PUT_LINE('Table does not exists');
ELSIF SQLCODE = -904 THEN
DBMS_OUTPUT.PUT_LINE('Invalid column name');
ELSE
DBMS_OUTPUT.PUT_LINE('Other error');
END IF;
END;
/
I'm trying to implement a pl sql program that export the content of all tables of a particular user in a file but i'm getting 'command not properly ended' problem whenever i run it.
here is my code:
create or replace procedure userTable(name dba_tables.owner%type)
is
cursor cur1 is select table_name from dba_tables where owner = upper(name);
cursor cur(tabName in varchar2) is select column_name from dba_tab_columns where owner = upper(name) and table_name = upper(tabName);
V$FILEP UTL_FILE.FILE_TYPE;
type dyncursor is ref cursor;
dyn dyncursor;
req varchar2(32767):='select to_char(';
lig Varchar2(32767);
i integer:=1;
begin
if existUser(name) = true then
V$FILEP := UTL_FILE.FOPEN('DIRT001','TEST09.UTL','W');
for vc1 in cur1 loop
for vc in cur(to_char(vc1.table_name)) loop
if (i=1) then
req:=req||vc.column_name||')';
i:=0;
else
req:=req||'||'||''','''||'||'||'to_char('||vc.column_name||')';
end if;
end loop;
req:=req||' from '||name||'.'||'to_char('||vc1.table_name||')';
open dyn for req;
loop
fetch dyn into lig;
exit when dyn%notfound;
dbms_output.put_line(lig);
UTL_FILE.PUT_LINE(V$FILEP,lig );
end loop;
close dyn;
end loop;
UTL_FILE.FCLOSE(V$FILEP);
else
dbms_output.put_line('user invalid');
end if;
end;
/
create or replace function existUser(name dba_users.username%type)
return boolean is
nb number :=0;
begin
select count(*) into nb from dba_users where username = upper(name);
if nb = 0 then
return false;
else
return true;
end if;
end;
/
Expanding on what has been mentioned in the comments, adding a DBMS_OUTPUT is going to show you that you have 'from schema.to_char(table_name)'.....
vc1.table_name & vc.column_name are already character (varchar2) so there is no need to do a to_char on them in the first place so just removing to_char from around all these is a good first step.
Then if it still does not work add the DBMS_OUTPUT as suggested by Arkadiusz Ćukasiewicz in the comments to see what other issues you may have.
I created a PL/SQL procedure that takes the name of user and shows a list of his tables' content. The problem is that I couldn't set the cursor to accept a different table name each time and show its content.
Here is my code which is not complete yet.
set serveroutput on;
create or replace procedure userTable(name dba_tables.owner%type)
is
cursor cur is select table_name from dba_tables where owner = upper(name);
cursor cur2(tab_name dba_tables.table_name%type) is select * from name.tab_name;
V$FILEP UTL_FILE.FILE_TYPE;
begin
if existUser(name) = true then
V$FILEP := UTL_FILE.FOPEN('DIRTEST','TEST15.UTL','W');
for x in cur loop
UTL_FILE.PUT_LINE(V$FILEP,to_char(x.table_name));
end loop;
UTL_FILE.FCLOSE(V$FILEP);
else
dbms_output.put_line('user invalid');
end if;
end;
/
How to wite EXECUTE IMMEDIATE in the cursor select Query.
CREATE OR REPLACE PROCEDURE biq_attendee_report (in_from_date IN DATE)
IS
l_cur_query VARCHAR2 (5000) := 'SELECT * from table X where c1='|| in_from_date;
CURSOR cur_attendee_data
IS
EXECUTE IMMEDIATE l_cur_query;
TYPE rec_attendee_data IS TABLE OF cur_attendee_data%ROWTYPE
INDEX BY PLS_INTEGER;
l_cur_attendee_data rec_attendee_data;
BEGIN
OPEN cur_attendee_data;
LOOP
FETCH cur_attendee_data BULK COLLECT INTO l_cur_attendee_data;
EXIT WHEN l_cur_attendee_data.COUNT = 0;
DBMS_OUTPUT.put_line ('here in first insert');
lrec := return_attendee_report ();
out_attendee_tab :=
return_attendee_arr_result (return_attendee_report ());
out_attendee_tab.DELETE;
FOR i IN 1 .. l_cur_attendee_data.COUNT
LOOP
BEGIN
NULL;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('Error occurred : ' || SQLERRM);
END;
END LOOP;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('HERE INSIIDE OTHERS' || SQLERRM);
END;
here I try to use initialize cursor outside begin block but it rises exception, how to write a dynamic query for the cursor,
cur_attendee_data is
EXECUTE IMMEDIATE l_cur_query;
Error(113,8): PLS-00103: Encountered the symbol "CUR_ATTENDEE_DATA" when expecting one of the following: := . ( # % ;
If you fetch all rows with BULK COLLECT INTO ... then you need only one loop, the second loop is useless.
The basic solution would be this one:
CREATE OR REPLACE PROCEDURE biq_attendee_report (in_from_date IN DATE) IS
l_cur_query VARCHAR2 (5000) := 'SELECT * from {table X} where c1=:d';
cur_attendee_data SYS_REFCURSOR;
TYPE rec_attendee_data IS TABLE OF {table X}%ROWTYPE;
l_cur_attendee_data rec_attendee_data;
BEGIN
OPEN cur_attendee_data FOR l_cur_query USING in_from_date;
FETCH cur_attendee_data BULK COLLECT INTO l_cur_attendee_data;
FOR i IN 1 .. l_cur_attendee_data.COUNT LOOP
-- do whatever you like to do with l_cur_attendee_data(i)
END LOOP;
CLOSE cur_attendee_data;
END;
However, I don't see any reason to make dynamic SQL. You can simply run
CREATE OR REPLACE PROCEDURE biq_attendee_report (in_from_date IN DATE) IS
cur_attendee_data SYS_REFCURSOR;
TYPE rec_attendee_data IS TABLE OF {table X}%ROWTYPE;
l_cur_attendee_data rec_attendee_data;
BEGIN
OPEN cur_attendee_data FOR SELECT * from {table X} where c1 = in_from_date;
FETCH cur_attendee_data BULK COLLECT INTO l_cur_attendee_data;
FOR i IN 1 .. l_cur_attendee_data.COUNT LOOP
-- do whatever you like to do with l_cur_attendee_data(i)
END LOOP;
CLOSE cur_attendee_data;
END;
You can use below code instead -
CREATE OR REPLACE PROCEDURE biq_attendee_report (in_from_date IN DATE)
IS
l_cur_query VARCHAR2 (100) := 'SELECT * from table X where c1=:in_from_date';
TYPE t_cur IS REF CURSOR;
cur_attendee_data t_cur
TYPE rec_attendee_data IS TABLE OF cur_attendee_data%ROWTYPE
INDEX BY PLS_INTEGER;
l_cur_attendee_data rec_attendee_data;
BEGIN
OPEN cur_attendee_data FOR l_cur_query USING in_from_date;
LOOP
FETCH cur_attendee_data BULK COLLECT INTO l_cur_attendee_data;
EXIT WHEN l_cur_attendee_data.COUNT = 0;
DBMS_OUTPUT.put_line ('here in first insert');
lrec := return_attendee_report ();
out_attendee_tab :=
return_attendee_arr_result (return_attendee_report ());
out_attendee_tab.DELETE;
FOR i IN 1 .. l_cur_attendee_data.COUNT
LOOP
BEGIN
NULL;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('Error occurred : ' || SQLERRM);
END;
END LOOP;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('HERE INSIIDE OTHERS' || SQLERRM);
END;
You need to use open cursor for '' as following:
CREATE OR REPLACE PROCEDURE biq_attendee_report (in_from_date IN DATE)
IS
l_cur_query VARCHAR2 (5000) := 'SELECT * from table X where c1='|| in_from_date;
cur_attendee_data SYS_REFCURSOR; -- JUST DECLARED THE CURSOR
--TYPE rec_attendee_data IS TABLE OF cur_attendee_data%ROWTYPE
-- INDEX BY PLS_INTEGER; -- this declaration must be at schema level
l_cur_attendee_data rec_attendee_data;
BEGIN
OPEN cur_attendee_data for l_cur_query; -- OPEN THE CURSOR WITH DYNAMIC QUERY
..
.. -- YOUR CODE AS IT IS
..
Cheers!!
PROCEDURE A(
...
BEGIN
stmt := 'select * from '||src;
execute immediate stmt;
dbms_output.put_line(??);
END A;
If you know the structure of the table named in "src" when writing the code then you can do this:
PROCEDURE A IS
...
l_cur sys_refcursor;
BEGIN
stmt := 'select * from '||src;
open l_cur for stmt;
loop
fetch l_cur into ??; -- record or list of variables that matches columns of "src"
exit when l_cur%notfound;
dbms_output.put_line(??);
end loop;
close l_cur;
END A;
If you will not know the structure until run time then you will need to use the DBMS_SQL package, which is very powerful but not simple.
I'm not sure wether this is working with your "execute immediate stmt" approach, but with static Sql, following is working for me:
for my_result in
(
select * from my_table tbl
where ...
order by tbl.my_id_col
) loop
dbms_output.put_line(my_result.field1 || ', ' || my_result.field2 || ...);
end loop;