Output a string in EXECUTE IMMEDIATE in Oracle PL/SQL - oracle

I am trying to use loop variable as a string and use it directly with EXECUTE IMMEDIATE in PL/SQL loop. Here is my code:
BEGIN
FOR i IN (
SELECT table_name FROM user_tables WHERE LOWER(table_name) LIKE 'tblequityreturnstest_%'
)
LOOP
vqs := 'DROP TABLE'||i||''
EXECUTE IMMEDIATE vqs;
END LOOP;
END;
But I am getting an error :
Error report -
ORA-06550: line 4, column 1:
PLS-00103: Encountered the symbol "EXECUTE" when expecting one of the following:
* & = - + ; < / > at in is mod remainder not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || member submultiset
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:

Your syntax is wrong, try
DECALRE
vqs VARCHAR2(100);
BEGIN
FOR i IN (SELECT table_name FROM user_tables WHERE LOWER(table_name) LIKE 'tblequityreturnstest_%') LOOP
vqs := 'DROP TABLE '||i.table_name;
EXECUTE IMMEDIATE vqs;
END LOOP;
END;
or even simpler
BEGIN
FOR i IN (SELECT table_name FROM user_tables WHERE LOWER(table_name) LIKE 'tblequityreturnstest_%') LOOP
EXECUTE IMMEDIATE 'DROP TABLE '||i.table_name;
END LOOP;
END;

Related

updating values in a loop by column name

I have a table with several columns, and I would like to eliminate spaces value (' ') from the values. The query is:
update table
set column_name = trim(both ' ' from column_name)
where column_name like '% '
and since the table contains around 55 columns so probably a loop would be a feasible idea instead of writing update statement for each and every column.
First I checked if looping is working:
declare
column_name varchar2(2048);
cursor pointer is
select column_name into column_name from user_tab_cols where table_name = 'TABLE_NAME';
begin
for x in pointer
loop
dbms_output.put_line(x.column_name);
end loop;
end;
yes, it is working. I get column names in dbms_output window.
Now,
Here is what I am trying to do which doesn't seem to work:
declare
column_var varchar2(2048);
cursor pointer is
select column_name into column_var from user_tab_cols where table_name = 'TABLE_NAME';
begin
for x in pointer
loop
update table_name
set x.column_var = trim(both ' ' from x.column_var)
where x.column_var like '% ';
commit;
end loop;
end;
This is, unfortunately not working. This is error I get:
ORA-06550: line 11, column 18:
PLS-00302: component 'COLUMN_VAR' must be declared.
ORA-06550: line 11, column 16:
PL/SQL: ORA-00904: "X"."COLUMN_VAR": invalid identifier
ORA-06550: line 9, column 10:
PL/SQL: SQL Statement ignored
Any idea where I am going off the track?
Thanks in advance :-)
I think you need to provide the actual column name, rather than the string representing the column name in the statement. Would an execute immediate work for you?
declare
column_var varchar2(2048);
cursor pointer is
select column_name into column_var from user_tab_cols where table_name = 'TABLE_NAME';
begin
for x in pointer
loop
execute immediate
'update table_name ' ||
'set '|| x.column_var ||' = trim(both '' '' from '|| x.column_var ||')'||
'where '|| x.column_var ||' like ''% ''';
commit;
end loop;
end;
You need to use dynamic sql for this
BEGIN
FOR t IN (select column_name from user_tab_cols where table_name = 'MyTable')
LOOP
EXECUTE IMMEDIATE
'update MyTable set '||t.column_name||' = trim(both '' '' from '||t.column_name||') where '||t.column_name||' like ''% ''';
END LOOP;
END;
/

pl/sql get all structure tables on oracle

I have problem about how to get all of list structure table using loop pl/sql,
i have syntax loop like bellow :
BEGIN
FOR x IN (SELECT table_name FROM user_tables)
LOOP
EXECUTE IMMEDIATE 'DESC' || x.table_name;
END LOOP;
COMMIT;
END;
and this is log output from sql developer
Error starting at line 14 in command:
BEGIN
FOR x IN (SELECT table_name FROM user_tables)
LOOP
EXECUTE IMMEDIATE 'DESC' || x.table_name;
END LOOP;
COMMIT;
END;
Error report:
ORA-00900: invalid SQL statement
ORA-06512: at line 4
00900. 00000 - "invalid SQL statement"
*Cause:
*Action:
Help me to solve this
Thanks
The DESC command is neither SQL nor plsql but a sqlplus command, so you can't use it in a plsql code.
More than that, why ? you can get all the values you need from USER_TAB_COLUMNS ...
Use DBMS_OUTPUT.put_line() instead:
BEGIN
FOR x IN (SELECT COLUMN_NAME, DATA_TYPE, NULLABLE FROM USER_TAB_COLUMNS)
LOOP
DBMS_OUTPUT.put_line(COLUMN_NAME || ' ' || DATA_TYPE || ' ' || NULLABLE );
END LOOP;
COMMIT;
END;
Of course this can be formatted nicer and there are more columns you can select ...
Consider this instead:
Select * from All_tab_Cols
or to be closer to what is returned from describe:
Select Owner, Table_name, ColumN_Name, Data_Type, Data_Length, Nullable
from all_tab_Cols;
To address your specific problem shouldn't it be:
EXECUTE IMMEDIATE 'DESC ' || x.table_name|| ';';
Missing space between desc & table name and ; is part of the SQL to run isn't it?
If you're trying to reverse engineer the schema then use the DBMS_Metadata package to do so, as it can also extract constraints, privileges, users etc.

PL SQL numeric or value error

On Executing this query, im having an error:
*Error report:
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at line 34
06502. 00000 - "PL/SQL: numeric or value error%s"*
.
My oracle version is:
Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
PL/SQL Release 9.2.0.1.0 - Production
please help me..
Regards,
DECLARE CURSOR c1 is SELECT TABLE_NAME FROM All_Tables WHERE TABLE_NAME NOT LIKE '%$%' AND Owner NOT IN ('WMSYS', 'EXFSYS', 'CTXSYS', 'WKSYS', 'SYSMAN', 'SYSTEM', 'FLOWS_030000', 'MDSYS', 'ORDSYS', 'DBSNMP', 'XDB', 'OLAPSYS');
col_names SYS_REFCURSOR; TYPE dat_res IS RECORD(tab_name VARCHAR2(1000),col_name VARCHAR2(1000));
TYPE dr is table of dat_res;
act_dat dr:= dr();
status NUMBER := 0;
cnt NUMBER := 1;
sql_stmt VARCHAR2(10000);
tab_name1 VARCHAR2(100);
col_name1 VARCHAR2(100);
BEGIN
FOR I IN C1 LOOP sql_stmt:= 'SELECT table_name,column_name FROM all_Tab_cols WHERE table_name = '||CHR(39)||I.table_name||CHR(39);
OPEN col_names FOR sql_stmt; LOOP FETCH col_names INTO tab_name1,col_name1;
EXIT WHEN col_names%NOTFOUND;
BEGIN
EXECUTE IMMEDIATE
'SELECT 1 FROM '||tab_name1|| ' WHERE REGEXP_LIKE('||'TO_CHAR('||col_name1||'), '||CHR(39)||'^[%][a-bA-B]'||CHR(39)||') '
INTO status;
EXCEPTION
WHEN VALUE_ERROR THEN NULL;
WHEN NO_DATA_FOUND THEN NULL;
WHEN OTHERS THEN NULL;
END;
IF (status = 1) THEN act_dat.extend; act_dat(cnt).tab_name:= tab_name1; act_dat(cnt).col_name:= col_name1; status := 0; cnt:= cnt + 1;
END IF; END LOOP;
CLOSE col_names;
END LOOP;
dbms_output.put_line('Table Name : Column Name');
FOR K IN act_dat.FIRST..act_dat.LAST LOOP insert into my_SAuditor_table VALUES (act_dat(K).tab_name, act_dat(K).col_name);
END LOOP;
Execute IMMEDIATE 'SELECT * FROM my_SAuditor_table';
END;
You might be looping over an empty collection.
You need to check that act_dr has some rows before using act_dr.FIRST and act_dr.LAST, otherwise you get null which is not a number.
This can be done with:
if act_dr.count > 0 then
FOR K IN act_dat.FIRST..act_dat.LAST LOOP
insert into my_SAuditor_table VALUES (act_dat(K).tab_name, act_dat(K).col_name);
END LOOP;
end if;
Problem is that column table name definitions are not consistent. In the end you end up inserting a 1000 bytes column in a 512 bytes column and the funny part is, you only read the column with a max length of 100 bytes.
I'd advise to cleanup the code.

Execute For Each Table in PLSQL

I want to the the number of records in all tables that match a specific name criteria. Here is the SQL I built
Declare SQLStatement VARCHAR (8000) :='';
BEGIN
SELECT 'SELECT COUNT (*) FROM ' || Table_Name || ';'
INTO SQLStatement
FROM All_Tables
WHERE 1=1
AND UPPER (Table_Name) LIKE UPPER ('MSRS%');
IF SQLStatement <> '' THEN
EXECUTE IMMEDIATE SQLStatement;
END IF;
END;
/
But I get the following error:
Error at line 1
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at line 3
Script Terminated on line 1.
How do I modify this so that it runs for all matching tables?
Update:
Based on an answer received, I tried the following but I do not get anything in the DBMS_OUTPUT
declare
cnt number;
begin
for r in (select table_name from all_tables) loop
dbms_output.put_line('select count(*) from CDR.' || r.table_name);
end loop;
end;
/
declare
cnt number;
begin
for r in (select owner, table_name from all_tables
where upper(table_name) like ('%MSRS%')) loop
execute immediate 'select count(*) from "'
|| r.owner || '"."'
|| r.table_name || '"'
into cnt;
dbms_output.put_line(r.owner || '.' || r.table_name || ': ' || cnt);
end loop;
end;
/
If you're selecting from all_tables you cannot count on having been given the grants necessary to select from the table name. You should therefore check for the ORA-00942: table or view does not exist error thrown.
As to the cause for your error: You get this error because the select statement returns a result set with more than one row (one for each table) and you cannot assign such a result set to a varchar2.
By the way, make sure you enable dbms_output with SET SERVEROUT ON before executing this block.

Go over all columns in tables in Oracle

This is a noobie question, most likely syntax one. But I am kinda lost...
I need to go over all columns in all tables in Oracle to generate trigger script. That trigger should insert the row being updated to a log table which is nearly the same as the original table. I thought I would just go over all the columns and just concatenate strings. Fairly easy but I am struggling with the syntax...
Here's what I have so far:
DECLARE
cursor tableNames is
select table_name
from user_tables
where table_name not like '%_A';
lSql varchar2(3000);
type t_columnRow is ref cursor;
v_columns t_columnRow;
begin
FOR tableName in tableNames
LOOP
open v_columns for select COLUMN_NAME from user_tab_columns where table_name = tableName;
for columnRow in v_columns LOOP
DBMS_OUTPUT.PUT_LINE(tableName || '.' || columnRow.COLUMN_NAME);
-- Here I would just concatenate the strings ....
END LOOP;
END LOOP;
End;
For that I am getting the following error:
Error at line 1
ORA-06550: line 14, column 84:
PLS-00382: expression is of wrong type
ORA-06550: line 16, column 22:
PLS-00221: 'V_COLUMNS' is not a procedure or is undefined
ORA-06550: line 16, column 5:
PL/SQL: Statement ignored
Try this:
BEGIN
FOR t IN (SELECT table_name FROM user_tables WHERE table_name not like '%_A')
LOOP
FOR c IN (SELECT column_name FROM user_tab_columns WHERE table_name = t.table_name)
LOOP
DBMS_OUTPUT.PUT_LINE(t.table_name||'.'||c.column_name);
-- Here I would just concatenate the strings ....
END LOOP;
END LOOP;
END;
You may be able to get away with something as simple as this:
DECLARE
cursor tableNames is
select table_name
from user_tables
where table_name not like '%_A';
lSql varchar2(3000);
begin
FOR tableName in tableNames
LOOP
for columnRow in (select COLUMN_NAME from user_tab_columns where table_name = tableName) LOOP
DBMS_OUTPUT.PUT_LINE(tableName || '.' || columnRow.COLUMN_NAME);
-- Here I would just concatenate the strings ....
END LOOP;
END LOOP;
End;

Resources