How can I drop all user tables in oracle?
I have problem with constraints. When I disable all it is still no possible.
BEGIN
FOR cur_rec IN (SELECT object_name, object_type
FROM user_objects
WHERE object_type IN
('TABLE',
'VIEW',
'MATERIALIZED VIEW',
'PACKAGE',
'PROCEDURE',
'FUNCTION',
'SEQUENCE',
'SYNONYM',
'PACKAGE BODY'
))
LOOP
BEGIN
IF cur_rec.object_type = 'TABLE'
THEN
EXECUTE IMMEDIATE 'DROP '
|| cur_rec.object_type
|| ' "'
|| cur_rec.object_name
|| '" CASCADE CONSTRAINTS';
ELSE
EXECUTE IMMEDIATE 'DROP '
|| cur_rec.object_type
|| ' "'
|| cur_rec.object_name
|| '"';
END IF;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('FAILED: DROP '
|| cur_rec.object_type
|| ' "'
|| cur_rec.object_name
|| '"'
);
END;
END LOOP;
FOR cur_rec IN (SELECT *
FROM all_synonyms
WHERE table_owner IN (SELECT USER FROM dual))
LOOP
BEGIN
EXECUTE IMMEDIATE 'DROP PUBLIC SYNONYM ' || cur_rec.synonym_name;
END;
END LOOP;
END;
/
If you just want a really simple way to do this.. Heres a script I have used in the past
select 'drop table '||table_name||' cascade constraints;' from user_tables;
This will print out a series of drop commands for all tables in the schema. Spool the result of this query and execute it.
Source: https://forums.oracle.com/forums/thread.jspa?threadID=614090
Likewise if you want to clear more than tables you can edit the following to suit your needs
select 'drop '||object_type||' '|| object_name || ';' from user_objects where object_type in ('VIEW','PACKAGE','SEQUENCE', 'PROCEDURE', 'FUNCTION', 'INDEX')
Another answer that worked for me is (credit to http://snipt.net/Fotinakis/drop-all-tables-and-constraints-within-an-oracle-schema/)
BEGIN
FOR c IN (SELECT table_name FROM user_tables) LOOP
EXECUTE IMMEDIATE ('DROP TABLE "' || c.table_name || '" CASCADE CONSTRAINTS');
END LOOP;
FOR s IN (SELECT sequence_name FROM user_sequences) LOOP
EXECUTE IMMEDIATE ('DROP SEQUENCE ' || s.sequence_name);
END LOOP;
END;
Note that this works immediately after you run it. It does NOT produce a script that you need to paste somewhere (like other answers here). It runs directly on the DB.
begin
for i in (select 'drop table '||table_name||' cascade constraints' tbl from user_tables)
loop
execute immediate i.tbl;
end loop;
end;
The simplest way is to drop the user that owns the objects with the cascade command.
DROP USER username CASCADE
SELECT 'DROP TABLE "' || TABLE_NAME || '" CASCADE CONSTRAINTS;'
FROM user_tables;
user_tables is a system table which contains all the tables of the user
the SELECT clause will generate a DROP statement for every table
you can run the script
The easiest way would be to drop the tablespace then build the tablespace back up. But I'd rather not have to do that. This is similar to Henry's except that I just do a copy/paste on the resultset in my gui.
SELECT
'DROP'
,object_type
,object_name
,CASE(object_type)
WHEN 'TABLE' THEN 'CASCADE CONSTRAINTS;'
ELSE ';'
END
FROM user_objects
WHERE
object_type IN ('TABLE','VIEW','PACKAGE','PROCEDURE','FUNCTION','SEQUENCE')
To remove all objects in oracle :
1) Dynamic
DECLARE
CURSOR IX IS
SELECT * FROM ALL_OBJECTS WHERE OBJECT_TYPE ='TABLE'
AND OWNER='SCHEMA_NAME';
CURSOR IY IS
SELECT * FROM ALL_OBJECTS WHERE OBJECT_TYPE
IN ('SEQUENCE',
'PROCEDURE',
'PACKAGE',
'FUNCTION',
'VIEW') AND OWNER='SCHEMA_NAME';
CURSOR IZ IS
SELECT * FROM ALL_OBJECTS WHERE OBJECT_TYPE IN ('TYPE') AND OWNER='SCHEMA_NAME';
BEGIN
FOR X IN IX LOOP
EXECUTE IMMEDIATE('DROP '||X.OBJECT_TYPE||' SCHEMA_NAME.'||X.OBJECT_NAME|| ' CASCADE CONSTRAINT');
END LOOP;
FOR Y IN IY LOOP
EXECUTE IMMEDIATE('DROP '||Y.OBJECT_TYPE||' SCHEMA_NAME.'||Y.OBJECT_NAME);
END LOOP;
FOR Z IN IZ LOOP
EXECUTE IMMEDIATE('DROP '||Z.OBJECT_TYPE||' SCHEMA_NAME.'||Z.OBJECT_NAME||' FORCE ');
END LOOP;
END;
/
2)Static
SELECT 'DROP TABLE "' || TABLE_NAME || '" CASCADE CONSTRAINTS;' FROM user_tables
union ALL
select 'drop '||object_type||' '|| object_name || ';' from user_objects
where object_type in ('VIEW','PACKAGE','SEQUENCE', 'PROCEDURE', 'FUNCTION')
union ALL
SELECT 'drop '
||object_type
||' '
|| object_name
|| ' force;'
FROM user_objects
WHERE object_type IN ('TYPE');
Please follow the below steps.
begin
for i in (select 'drop table '||table_name||' cascade constraints' tb from user_tables)
loop
execute immediate i.tb;
end loop;
commit;
end;
purge RECYCLEBIN;
Related
I am trying to change all PK constraint names. Below is the code I am trying to run:
BEGIN
FOR i IN (
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM ALL_CONSTRAINTS
WHERE OWNER = 'SOME_SCHEME'
AND TABLE_NAME NOT LIKE 'flyway%'
AND TABLE_NAME NOT LIKE 'BIN%'
AND CONSTRAINT_TYPE = 'P')
LOOP
dbms_output.put_line(i.CONSTRAINT_NAME || i.table_name);
EXECUTE IMMEDIATE 'ALTER TABLE i.table_name rename constraint i.constraint_name to i.table_name || ''_PK''';
END LOOP;
END;
I am getting the following error:
SQL Error [946] [42000]: ORA-00946: missing TO keyword
ORA-06512: at line 17
ORA-06512: at line 17
Why does it say TO is missing when it is not?
How can this problem be solved?
If you use dbms_output to display the statement before you execute it, you'll see it's malformed; whatever the table and constraint, the statement you are currently trying to execute is, literally:
ALTER TABLE i.table_name rename constraint i.constraint_name to i.table_name || '_PK'
The i.* parts are not variables or values, they are literally those strings. Running that statement manually gets the same error, of course.
You need to concatenate the loop variable values into the statement; you also need to specify the owner, since you're looking at all_tables, and you might as well quote the names:
DECLARE
l_stmt varchar2(4000);
BEGIN
FOR ...
LOOP
dbms_output.put_line(i.CONSTRAINT_NAME || i.table_name);
l_stmt := 'ALTER TABLE SOME_SCHEME."' || i.table_name || '"'
|| ' rename constraint "' || i.constraint_name || '"'
|| ' to "' || i.table_name || '_PK"';
dbms_output.put_line(l_stmt);
EXECUTE IMMEDIATE l_stmt;
END LOOP;
END;
/
which generates something more like:
ALTER TABLE SOME_SCHEME."SDO_DATUMS" rename constraint "DATUM_PRIM" to "SDO_DATUMS_PK"
db<>fiddle
I've hard-coded the SOME_SCHEME name you use in the loop query; you could also get that from the query itself by adding OWNER to the select list, and then concatenate that in as well (again, quoted to be overly cautious). Or set that in a local variable and use that in both places, as #MTO suggested in a comment.
If you will only run this as the SOME_SCHEME user then you can query user_constraints instead:
DECLARE
l_stmt varchar2(4000);
BEGIN
FOR i IN (
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM USER_CONSTRAINTS
WHERE TABLE_NAME NOT LIKE 'flyway%' -- are these really quoted lower-case?
AND TABLE_NAME NOT LIKE 'BIN%'
AND CONSTRAINT_TYPE = 'P'
AND CONSTRAINT_NAME != TABLE_NAME || '_PK'
)
LOOP
l_stmt := 'ALTER TABLE "' || i.table_name || '"'
|| ' RENAME constraint "' || i.constraint_name || '"'
|| ' TO "' || i.table_name || '_PK"';
dbms_output.put_line(l_stmt);
EXECUTE IMMEDIATE l_stmt;
END LOOP;
END;
/
db<>fiddle with example tables, with quoted and unquoted identifiers.
You might also want your loop query to include:
AND CONSTRAINT_NAME != TABLE_NAME || '_PK'
... so you don't touch constraints that already have the name pattern you want.
I want to do select column_name from table_name where column_name.
table_name should be coming from cursor.
Query:
DECLARE
COLUMN_NAME VARCHAR(50);
TABLE_NAME VARCHAR(100);
schema_name VARCHAR(100);
A VARCHAR(100);
B VARCHAR(100);
CURSOR col_cursor IS
select col.owner as schema_name,
col.table_name,
col.column_name
from sys.all_tab_columns col
inner join sys.all_tables t
on col.owner = t.owner and
col.table_name = t.table_name
where col.owner = 'PIYUSH1910_BEFORE'
AND
DATA_TYPE = 'NUMBER'
AND
DATA_PRECISION IS NULL
AND
col.TABLE_NAME NOT LIKE '%ER%';
BEGIN
OPEN col_cursor;
LOOP
FETCH col_cursor INTO schema_name,TABLE_NAME,COLUMN_NAME;
EXIT WHEN col_cursor%NOTFOUND;
EXECUTE IMMEDIATE ' SELECT '||COLUMN_NAME ||' INTO A from ' || Table_Name || 'WHERE'||COLUMN_NAME||'- TRUNC('||COLUMN_NAME||',2) > 0';
dbms_output.Put_line(A);
END LOOP;
CLOSE col_cursor;
END
But its throwing this error:
Error report - ORA-00933: SQL command not properly ended. ORA-06512: at line 29 00933. 00000 - "SQL command not properly ended *Cause: *Action:
INTO clause must be at the end while using the EXECUTE IMMEDIATE as follows:
EXECUTE IMMEDIATE ' SELECT '||COLUMN_NAME ||' from '
|| Table_Name || ' WHERE '||COLUMN_NAME||'- TRUNC('||COLUMN_NAME||',2) > 0'
INTO A;
Also, space before and after WHERE keyword is added in the above solution.
Change your EXECUTE IMMEDIATE to:
EXECUTE IMMEDIATE ' SELECT '|| COLUMN_NAME || ' from ' || Table_Name ||
' WHERE ' || COLUMN_NAME || '- TRUNC('||COLUMN_NAME||',2) > 0'
INTO A;
This moves the INTO clause to the correct position (in this case it's part of the EXECUTE IMMEDIATE rather than being part of the SELECT) and reformats the code slightly so that column names are separated from e.g. the WHERE keyword.
I have below Select query which will generate delete statements to delete all objects in schema.
select 'DROP '||OBJECT_TYPE||' '||OWNER||'.'||OBJECT_NAME
|| case when OBJECT_TYPE = 'TABLE'
then ' CASCADE CONSTRAINTS PURGE' else '' end
||';'
from all_objects
where OWNER = 'RATOR_MONITORING';
I want to create batch file and suppose that instead of generating delete statements separetly I can create may be cursor or something and save it in batch file and run the batch file to delete all contents in schema. How to do it?
You can find many script in the Internet. Neither of them work on 100%. There can we various gotchas. Like scheduler chains or materialized view groups.
This is the one I use (it is also inspired by one I found in the Internet)
set serveroutput on size unlimited
declare
v_ItemCount integer;
begin
SELECT count(*)
INTO v_ItemCount
FROM ALL_OBJECTS AO
WHERE AO.OWNER = '&USER'
AND AO.OBJECT_TYPE NOT IN ('INDEX', 'LOB')
AND AO.OBJECT_NAME NOT LIKE 'BIN$%';
while (v_ItemCount > 0) loop
for v_Cmd in (SELECT 'drop ' || AO.OBJECT_TYPE || ' ' || '"'||AO.OWNER||'"'|| '.' || '"'||AO.OBJECT_NAME||'"' ||
DECODE(AO.OBJECT_TYPE,
'TABLE',
' CASCADE CONSTRAINTS',
'') as DROPCMD,
AO.OWNER,
AO.OBJECT_TYPE,
AO.OBJECT_NAME
FROM ALL_OBJECTS AO
WHERE AO.OWNER = '&USER'
AND AO.OBJECT_TYPE NOT IN ('INDEX', 'LOB')
AND AO.OBJECT_NAME NOT LIKE 'BIN$%')
loop
begin
if v_Cmd.OBJECT_TYPE = 'SCHEDULE' then
DBMS_SCHEDULER.DROP_SCHEDULE(v_Cmd.OWNER||'.'||v_Cmd.OBJECT_NAME, true);
ELSIF v_Cmd.OBJECT_TYPE = 'JOB' then
DBMS_SCHEDULER.DROP_JOB(v_Cmd.OWNER||'.'||v_Cmd.OBJECT_NAME, true);
ELSIF v_Cmd.OBJECT_TYPE = 'PROGRAM' then
DBMS_SCHEDULER.DROP_PROGRAM(v_Cmd.OWNER||'.'||v_Cmd.OBJECT_NAME, true);
else
execute immediate v_Cmd.dropcmd;
end if;
dbms_output.put_line(v_Cmd.dropcmd);
exception
when others then
null; -- ignore errors
end;
end loop;
SELECT count(*)
INTO v_ItemCount
FROM ALL_OBJECTS AO
WHERE AO.OWNER = '&USER'
AND AO.OBJECT_TYPE NOT IN ('INDEX','LOB')
AND AO.OBJECT_NAME NOT LIKE 'BIN$%';
end loop;
execute immediate 'purge dba_recyclebin';
end;
Here is the script
begin
for i in (select * from dba_objects where owner = 'SO' and object_type <> 'TABLE')
loop
execute immediate 'drop ' || i.object_type || ' ' || i.object_name;
end loop;
for j in (select * from dba_objects where owner = 'SO' and object_type = 'TABLE')
loop
execute immediate 'drop ' || j.object_type || ' ' || j.object_name || ' cascade constraints';
end loop;
end;
/
This link provides details about how to create shell script or batch script to run sql scripts.
https://oracle-base.com/articles/misc/oracle-shell-scripting
Here we go i have compiled a shell to perform the Purge Schema. Let me know if this helps.
#weekly report
#!/bin/ksh
export ORACLE_HOME=/opt/oracle/product/1020
export PATH=$ORACLE_HOME/bin:$PATH:.
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
ABC=`sqlplus -s <username>/<password>#<sid> <<+
set sqlbl on;
set serveroutput on;
DECLARE
v_ItemCount INTEGER;
BEGIN
SELECT COUNT(*)
INTO v_ItemCount
FROM ALL_OBJECTS AO
WHERE AO.OWNER = '&USER'
AND AO.OBJECT_TYPE NOT IN ('INDEX', 'LOB')
AND AO.OBJECT_NAME NOT LIKE 'BIN$%';
WHILE (v_ItemCount > 0)
LOOP
FOR v_Cmd IN
(SELECT 'drop '
|| AO.OBJECT_TYPE
|| ' '
|| '"'
||AO.OWNER
||'"'
|| '.'
|| '"'
||AO.OBJECT_NAME
||'"'
|| DECODE(AO.OBJECT_TYPE, 'TABLE', ' CASCADE CONSTRAINTS', '') AS DROPCMD,
AO.OWNER,
AO.OBJECT_TYPE,
AO.OBJECT_NAME
FROM ALL_OBJECTS AO
WHERE AO.OWNER = '&USER'
AND AO.OBJECT_TYPE NOT IN ('INDEX', 'LOB')
AND AO.OBJECT_NAME NOT LIKE 'BIN$%'
)
LOOP
BEGIN
IF v_Cmd.OBJECT_TYPE = 'SCHEDULE' THEN
DBMS_SCHEDULER.DROP_SCHEDULE(v_Cmd.OWNER||'.'||v_Cmd.OBJECT_NAME, true);
ELSIF v_Cmd.OBJECT_TYPE = 'JOB' THEN
DBMS_SCHEDULER.DROP_JOB(v_Cmd.OWNER||'.'||v_Cmd.OBJECT_NAME, true);
ELSIF v_Cmd.OBJECT_TYPE = 'PROGRAM' THEN
DBMS_SCHEDULER.DROP_PROGRAM(v_Cmd.OWNER||'.'||v_Cmd.OBJECT_NAME, true);
ELSE
EXECUTE immediate v_Cmd.dropcmd;
END IF;
dbms_output.put_line(v_Cmd.dropcmd);
EXCEPTION
WHEN OTHERS THEN
NULL; -- ignore errors
END;
END LOOP;
SELECT COUNT(*)
INTO v_ItemCount
FROM ALL_OBJECTS AO
WHERE AO.OWNER = '&USER'
AND AO.OBJECT_TYPE NOT IN ('INDEX','LOB')
AND AO.OBJECT_NAME NOT LIKE 'BIN$%';
END LOOP;
EXECUTE immediate 'purge dba_recyclebin';
END;
/
exit
+`
Is there a way to grant all privileges to a user on Oracle schema? I tried the following command but it only grants permission on specific tables in a schema. What I want is to give this user all permissions on a given schema.
GRANT ALL ON MyTable TO MyUser;
You can do it in a loop and grant by dynamic SQL:
BEGIN
FOR objects IN
(
SELECT 'GRANT ALL ON "'||owner||'"."'||object_name||'" TO MyUser' grantSQL
FROM all_objects
WHERE owner = 'MY_SCHEMA'
AND object_type NOT IN
(
--Ungrantable objects. Your schema may have more.
'SYNONYM', 'INDEX', 'INDEX PARTITION', 'DATABASE LINK',
'LOB', 'TABLE PARTITION', 'TRIGGER'
)
ORDER BY object_type, object_name
) LOOP
BEGIN
EXECUTE IMMEDIATE objects.grantSQL;
EXCEPTION WHEN OTHERS THEN
--Ignore ORA-04063: view "X.Y" has errors.
--(You could potentially workaround this by creating an empty view,
-- granting access to it, and then recreat the original view.)
IF SQLCODE IN (-4063) THEN
NULL;
--Raise exception along with the statement that failed.
ELSE
raise_application_error(-20000, 'Problem with this statement: ' ||
objects.grantSQL || CHR(10) || SQLERRM);
END IF;
END;
END LOOP;
END;
/
If you want to grant privileges to all tables in a specific schema:
BEGIN
FOR x IN (select *from all_tables where OWNER = 'schema name')
LOOP
EXECUTE IMMEDIATE 'GRANT SELECT ON '||x.OWNER||'.'|| x.table_name || TO 'user name';
END LOOP;
END;
begin
for x in (select *from all_tables where owner = 'SYS')
loop
execute immediate 'grant select on '||x.owner||'.'|| x.table_name || ' to ' || 'your_user';
end loop;
end;
I have just started to learn PL/SQL. Following a post in stackoverflow, I have written a script to search a certain value in Oracle as below:
DECLARE
match_count INTEGER;
v_owner VARCHAR2(255);
v_search_value NUMBER;
BEGIN
v_owner:='USERA USERB';
v_search_value:=4823.0;
EXECUTE IMMEDIATE
'INSERT INTO TMP SELECT owner, table_name, column_name FROM all_tab_cols WHERE instr(:1, owner)>0 AND data_type like ''%NUMBER%''' USING v_owner;
commit;
FOR t IN (SELECT owner, table_name, column_name FROM TMP) LOOP
EXECUTE IMMEDIATE
'SELECT COUNT(*) FROM '||t.owner||'.'||t.table_name||' WHERE '||t.column_name||'= :1'
INTO match_count
USING v_search_value;
IF match_count > 0 THEN
EXECUTE IMMEDIATE
'INSERT INTO RESULT VALUES(:1, :2, :3, :4)'
USING t.owner, t.table_name, t.column_name, match_count;
commit;
END IF;
END LOOP;
END;
The table TMP and RESULT have been properly created before executing the script. However, when I run the script, I get an ORA-01788 error saying that "connect by clause required" on line 12. I wonder why the code cause this error and how to change the script to be executed properly. Thanks!
You probably have a table with a column called level (as Florin suggested while I wasn't looking), which is a reserved word.
It may be in any case - not just level, but LEVEL, or Level - so to check you could do:
select owner, table_name, column_name
from all_tab_columns
where upper(column_name) = 'LEVEL';
Or to look for any reserved words in use (though this won't always find all potential problems):
select atc.owner, atc.table_name, atc.column_name, vrw.keyword
from all_tab_columns atc
join v$reserved_words vrw on vrw.keyword = upper(atc.column_name);
You could run similar queries against all_tables or all_objects to find potential problems elsewhere.
If I run a modified version of your query which doesn't bother with the TMP table - not sure why you'd want that; doesn't use dynamic SQL for the inserts; doesn't commit (which is an odd thing to do in a block - you don't need to do it after every insert anyway); and just for my benefit just displays the matches instead of needing to build a results table:
declare
match_count integer;
v_owner varchar2(255);
v_search_value number;
begin
v_owner := 'USERA USERB';
v_search_value := 4823.0;
for t in (
select owner, table_name, column_name
from all_tab_cols
where instr(v_owner, owner) > 0
and data_type like '%NUMBER%'
) loop
execute immediate
'select count(*) from ' || t.owner ||'.'|| t.table_name
|| ' where ' || t.column_name || ' = :1'
into match_count using v_search_value;
if match_count > 0 then
-- insert into results values (t.owner, t.table_name,
-- t.column_name, match_count);
dbms_output.put_line('Matched ' || t.owner ||'.'|| t.table_name
||'.'|| t.column_name ||': '|| match_count);
end if;
end loop;
end;
/
... this completes successfully. If I add a table with a level column:
create table t42 ("LEVEL" number);
... and then run the same block again then I also get:
ORA-01788: CONNECT BY clause required in this query block
ORA-06512: at line 14
01788. 00000 - "CONNECT BY clause required in this query block"
*Cause:
*Action:
Aside from avoiding reserved words in object names, you can make this work by enclosing all of your object names in double-quotes:
execute immediate
'select count(*) from "' || t.owner ||'"."'|| t.table_name
|| '" where "' || t.column_name || '" = :1'
into match_count using v_search_value;
This will also cope with mixed-case object names, which you should also avoid.