I know this question may ask many times but I could not find one line SQL statement.
I remember I did it before but now I could not remember how I did
I want to drop all tables whose name starts with "EXT_". Is it possibile to make it happen with one line SQL statement.
You could use a short anonymous block to do this.
BEGIN
FOR c IN ( SELECT table_name FROM user_tables WHERE table_name LIKE 'EXT_%' )
LOOP
EXECUTE IMMEDIATE 'DROP TABLE ' || c.table_name;
END LOOP;
END;
It's not possible with only one statement. Usually, I write a sql to get all the tables and then execute the results:
select 'drop table ' || table_name || ';'
from user_tables
where table_name like 'EXT_%';
This code will DROP not only EXT_% tables, it will act as DROP EXT% also.
Underscore is as special wildcard that acts as '%' but for a single character.
BEGIN
FOR c IN ( SELECT table_name FROM user_tables WHERE table_name LIKE 'EXT_%' )
LOOP
EXECUTE IMMEDIATE 'DROP TABLE ' || c.table_name;
END LOOP;
END;
In order to achieved desired results you should change your code the way below
BEGIN
FOR c IN ( SELECT table_name FROM user_tables WHERE table_name LIKE 'EXT\_%' ESCAPE '\')
LOOP
EXECUTE IMMEDIATE 'DROP TABLE ' || c.table_name;
END LOOP;
END;
It escapes underscore char in order to be trated literally, ESCAPE '\' modifier indicates that escape char is '\'
In most of cases you will find contraints violations. In that case, this script can help you:
DECLARE
c_action CONSTANT VARCHAR2(10) := 'DROP';
BEGIN
FOR c IN ( SELECT table_name FROM user_tables WHERE table_name LIKE 'STARTINGTEXT_%' )
LOOP
FOR reg IN (SELECT uc.table_name,
uc.constraint_name
FROM user_constraints uc
WHERE uc.table_name IN (c.table_name)) LOOP
EXECUTE IMMEDIATE 'ALTER TABLE ' || reg.table_name || ' ' || c_action ||
' CONSTRAINT ' || reg.constraint_name ;
END LOOP;
END LOOP;
COMMIT;
FOR c IN ( SELECT table_name FROM user_tables WHERE table_name LIKE 'STARTINGTEXT_%' )
LOOP
EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || c.table_name;
EXECUTE IMMEDIATE 'DROP TABLE ' || c.table_name;
END LOOP;
END;
Related
I work wirh oracle Database. I have a plsql code where i run a query in a loop for multiple tables. so, table name is a variable in my code. I would like to have another variable (a single number) that I can call inside the loop and every time it counts the total rows of each table for me
declare
Cursor C_TABLE is
select trim(table_name) as table_name
from all_tables
where table_name in ('T1', 'T2', 'T3');
V_ROWNUM number;
begin
for m in C_TABLE
loop
for i in ( select column_name
from (
select c.column_name
from all_tab_columns c
where c.table_name = m.table_name
and c.owner = 'owner1'
)
)
loop
--I have this:
execute immediate ' insert into MY-table value (select ' || i.column_name || ' from ' || m.table_name || ')';
--I want this but it does not work of course:
V_ROWNUM := execute immediate 'select count(*) from ' || m.table_name;
execute immediate ' insert into MY-table value (select ' || i.column_name || ', ' || V_ROWNUM || ' from ' || m.table_name || ')';
end loop;
end loop;
end;
/
I count not use the "insert into" because I am not selecting from 1 table but the table I want to select from changes every round.
There are three things wrong with your dynamic SQL.
EXECUTE IMMEDIATE is not a function: the proper syntax is execute immediate '<<query>>' into <<variable>>.
An INSERT statement takes a VALUES clause or a SELECT but not both. SELECT would be very wrong in this case. Also note that it's VALUES not VALUE.
COLUMN_NAME is a string literal in the dynamic SQL so it needs to be in quotes. But because the SQL statement is itself a string, quotes in dynamic strings need to be escaped so it should be `'''||column_name||'''.
So the corrected version will look something like this
declare
Cursor C_TABLE is
select trim(table_name) as table_name
from all_tables
where table_name in ('T1', 'T2', 'T3');
V_ROWNUM number;
begin
for m in C_TABLE
loop
for i in ( select column_name
from (
select c.column_name
from all_tab_columns c
where c.table_name = m.table_name
and c.owner = 'owner1'
)
)
loop
execute immediate 'select count(*) from ' || m.table_name into V_ROWNUM;
execute immediate 'insert into MY_table values ( ''' || i.column_name || ''', ' || V_ROWNUM || ')';
end loop;
end loop;
end;
/
Dynamic SQL is hard because it turns compilation errors into runtime errors. It is good practice to write the statements first as static SQL. Once you have got the basic syntax right you can convert it into dynamic SQL.
you can't assign the result of execute immediate to a variable. it is not a function.
but you can do it by using the into_clause e.g.
execute immediate 'select count(*) from ' || m.table_name into V_ROWNUM ;
I have Oracle 11g. I would like to 'loop' this code through multiple tables t1 is already there, but I need to do this for 4 tables (t1,t2,t3, and t4):
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE t1';
EXECUTE IMMEDIATE 'DROP TABLE t1';
EXCEPTION WHEN OTHERS THEN
IF SQLCODE !=-942 THEN
RAISE;
END IF;
END;
I can change this manually, but the code then swells and I would really like to control it just once.:-) Also the tables may not be sequentially labelled. Thank you in advance.
Kate
Make a loop where you select the table names from dual. You could also have a table containing the names and select from this.
BEGIN
for t in
(
select 't1' as table_name from dual
union all
select 't2' as table_name from dual
union all
select 't3' as table_name from dual
union all
select 't4' as table_name from dual
)
loop
EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || t.table_name;
EXECUTE IMMEDIATE 'DROP TABLE ' || t.table_name;
end loop;
EXCEPTION WHEN OTHERS THEN
IF SQLCODE !=-942 THEN
RAISE;
END IF;
END;
There is no need to truncate a table before you drop it, so the drop table is sufficient. Additionally, I'd add the purge modifier so that it doesn't clutter the recycle bin.
begin
for t in (select table_name from user_tables
where regexp_like(table_name, '^T[1-4]$')) loop
execute immediate 'drop table ' || t.table_name || ' purge';
end loop;
end;
/
Of course, you can drop the table in a specific procedure:
declare
procedure drop_table(t in varchar2) is begin
execute immediate 'drop table ' || t || ' purge';
exception when others then
if sqlcode != -942 then
raise;
end if;
end drop_table;
begin
drop_table('T1');
drop_table('T2');
drop_table('T3');
drop_table('T4');
end;
/
I need to update a column matching a specific pattern in all tables in an oracle database.
For example I have in all tables this column *_CID with is a foreign key to master table witch has a primary key CID
Thanks
You can use the naming convention and query all_tab_columns
declare
cursor c is
select table_owner , column_name, table_name from all_tab_columns where column_name like '%_CID';
begin
for x in c loop
execute immediate 'update ' || x.table_owner || '.' || x.table_name ||' set ' || x.column_name||' = 0';
end loop;
end;
If you have valid Fk's you can also use all_tab_constraints the fetch enabled FK's for your main table and fetch the columns name of the r_constraint_name.
I found a solution to my question:
BEGIN
FOR x IN (SELECT owner, table_name, column_name FROM all_tab_columns) LOOP
EXECUTE IMMEDIATE 'update ' || x.owner || '.' || x.table_name ||' set ' || x.column_name||' = 0 where '||x.column_name||' = 1';
END LOOP;
END;
thanks
I am trying to search every view in the database for a specific value of something like '%THIS%'
I came up with this plsql code
DECLARE
match_count INTEGER;
BEGIN
FOR t IN (SELECT name FROM user_dependencies where type = 'VIEW') LOOP
EXECUTE IMMEDIATE
'SELECT COUNT(*) FROM '|| t.name || ' Where Column_Name LIKE ''%THIS%'' '
INTO match_count;
IF match_count > 0 THEN
dbms_output.put_line( t.name ||' '||match_count );
END IF;
END LOOP;
END;
But when I try to run it, I get an invalid identifier error for the column name in the execute immeadiate query.
The problem to me is obvious that not every view has the Column_Name, but I can't figure out how I can check to see if the column exists before running the query as I loop through all of the views.
I was also able to use a slightly modified version of this to run through all of the tables, and while they do not all have that column, I did not run in to this issue.
Edit: I am including the plsql code that I was able to use to loop through the tables.
DECLARE
match_count INTEGER;
BEGIN
FOR t IN (SELECT table_name, column_name FROM all_tab_columns
where table_name LIKE 'THIS%' and data_type = 'VARCHAR2' AND column_name = 'Column_name') LOOP
EXECUTE IMMEDIATE
'SELECT COUNT(*) FROM '||t.table_name || ' Where Column_name LIKE ''%THIS%'' '
INTO match_count;
IF match_count > 0 THEN
dbms_output.put_line( t.table_name ||' '||t.column_name||' '||match_count );
END IF;
END LOOP;
END;
I'm assuming this is Oracle since you tagged pl/sql. You can use Oracle's metadata tables to see what columns a table/view has. Specifically USER_TAB_COLUMNS.
select count(*)
from user_tab_columns
where table_name = [name of view]
and column_name = [name of column]
This should query every view that has a column_name like '%START%'
declare
cursor getViews is
select table_name, column_name from user_tab_cols where table_name in
(select view_name from user_views)
and column_name like '%START%';
myResult number;
BEGIN
for i in getViews
LOOP
execute immediate 'select count(*) from '||i.table_name into myResult;
END LOOP;
END;
I want to get the distinct dates in a column called "YMDH" from each table in a schema where that column exists. I figured that I needed to use nested cursors (something I've not done before) and came up with the following code:
CREATE OR REPLACE PROCEDURE DistinctDates AS
sql_statement1 varchar2(200);
sql_statement2 varchar2(200);
results varchar2(15);
ColumnExist integer;
BEGIN
for cursor_rec in (SELECT * FROM user_objects WHERE object_type='TABLE'
AND object_name NOT LIKE 'TM%') loop
sql_statement1 := 'select count (*) from user_tab_columns where table_name=' || '''' || cursor_rec.object_name || '''' || ' and column_name=' || '''' ||'YMDH' || '''';
execute immediate sql_statement1 into ColumnExist;
if ColumnExist = 1 then
for inner_cursor_rec in (select distinct(ymdh) from cursor_rec.object_name) loop
null;
end loop;
end if;
end loop;
END DistinctDates;
SQL Developer is complaining about the select statement for the inner cursor. The error message is:
Error(18,32): PL/SQL: SQL Statement ignored
Error(18,70): PL/SQL: ORA-00942: table or view does not exist
So it's not recognizing the reference to the outer cursor. How do I pass the table name (which is the cursor_rec.object_name) to the inner cursor?
You have used dynamic SQL where it is not needed, and have not used it where it is needed!
The check to see if the table has a column called 'YMDH' can be incorporated into the first query, giving this code:
CREATE OR REPLACE PROCEDURE DistinctDates AS
sql_statement varchar2(200);
rc sys_refcursor;
ymdh_value ????; -- Appropriate data type
BEGIN
for cursor_rec in (SELECT t.table_name
FROM user_tables t
JOIN user_tab_columns c ON c.table_name = t.table_name
WHERE t.table_name NOT LIKE 'TM%'
AND c.column_name='YMDH')
loop
sql_statement := 'select distinct(ymdh) from ' || cursor_rec.table_name;
open rc for sql_statement;
loop
fetch rc into ymdh_value;
exit when rc%notfound;
null;
end loop;
close rc;
end loop;
END DistinctDates;