SELECT 'ALTER TABLE ' || uc.table_name || ' DROP CONSTRAINT ' || uc.constraint_name FROM user_constraints uc WHERE constraint_type = 'R';
returns i.e. some statements which I can execute manually like:
ALTER TABLE APPLICATIONUSERROLE DROP CONSTRAINT APP_APPUSERROLE_FK1
ALTER TABLE APPLICATIONUSERROLE DROP CONSTRAINT USER_APPUSERROLE_FK1
ALTER TABLE APPLICATIONUSERROLE DROP CONSTRAINT ROLE_APPUSERROLE_FK1
What do I have to do to execute them automatically?
For example I tried:
EXECUTE IMMEDIATE (SELECT 'ALTER TABLE ' || uc.table_name || ' DROP CONSTRAINT ' || uc.constraint_name FROM user_constraints uc WHERE constraint_type = 'R');
but thats not working at all throwing some errors.
Thanks in advance.
begin
for i in (SELECT 'ALTER TABLE ' || uc.table_name || ' DROP CONSTRAINT ' || uc.constraint_name as sql_text FROM user_constraints uc WHERE constraint_type = 'R')
loop
execute immediate i.sql_text;
end loop;
end;
Related
I am trying to write a SQL script that guesses foreign keys. My approach is to eliminate every column that can't be a foreign key. The rest would be manual work.
SELECT
atc1.table_name atc1_tn,
atc1.column_name atc1_cn,
atc2.table_name atc2_tn,
atc2.column_name atc2_cn
FROM
all_tab_cols atc1,
all_tab_cols atc2
WHERE
atc1.data_type = 'NUMBER'
AND atc1.data_type = atc2.data_type
AND atc1.table_name != atc2.table_name
AND atc1.high_value <= atc2.high_value
AND atc1.num_distinct <= atc2.num_distinct
At this point I get all possible matching columns but that is still not accurate enough.
The next step would be to check if every entry in atc1.column_name exists in atc2.column_name, because if not it can't be a foreign key.
How can I add that condition to my where clause?
The approach is:
Select
(execute immediate 'select '||ATC1_CN||' from '||ATC1_TN||'') as a,
(execute immediate 'select '||ATC2_CN||' from '||ATC2_TN||'') as b
from my_temp_table
where a not in b;
But that doesn't work as expected, because I can't use the table names in a string for a query.
Try the below for existing foreign keys
SELECT a.table_name, a.column_name, a.constraint_name, c.owner,
-- referenced pk
c.r_owner, c_pk.table_name r_table_name, c_pk.constraint_name r_pk
FROM all_cons_columns a
JOIN all_constraints c ON a.owner = c.owner
AND a.constraint_name = c.constraint_name
JOIN all_constraints c_pk ON c.r_owner = c_pk.owner
AND c.r_constraint_name = c_pk.constraint_name
WHERE c.constraint_type = 'R'
For potential foreign keys here are some pointers
The data type of foreign and referenced key should be same
The values in foreign and referenced key columns should be same
The child and parent tables must be on the same database
For query you can use the below
declare
prec number;
begin
for rec in (SELECT atc1.table_name atc1_tn,
atc1.column_name atc1_cn,
atc2.table_name atc2_tn,
atc2.column_name atc2_cn
FROM user_tab_cols atc1, user_tab_cols atc2
WHERE atc1.data_type = 'NUMBER'
AND atc1.data_type = atc2.data_type
AND atc1.table_name != atc2.table_name
AND atc1.high_value <= atc2.high_value
AND atc1.num_distinct <= atc2.num_distinct
) loop
execute immediate 'select count(1) from ' || rec.atc1_tn ||
' a where EXISTS (SELECT 1 FROM ' || rec.atc2_tn ||
' b where a.' || rec.atc1_cn || '!=' || ' b.' ||
rec.atc2_cn || ' )'
into prec;
if prec = 0 Then
dbms_output.put_line('potential foreign key rec:table1 ' ||
rec.atc1_tn || ' table2: ' || rec.atc2_tn ||
' column1: ' || rec.atc1_cn || ' column2: ' ||
rec.atc2_cn);
end if;
end loop;
end;
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'm trying to drop a schema in oracle 11g on our dev environment and I get back SQL Error: No more data to read from socket. There is no load on the schema as it's just a dev db. It's a small db without anything crazy going on. I see this error all the time. Restarting the instance sometimes resolves the problem. I can't seem to find any information that would point to a solution. Thanks!
I understand that this message often arises due to a bug. Also, when it appears an entry in your alert log and/or a trace file will contain more detail on what the error might actually be. To find your trace file for the session run:
select U_DUMP.value
|| '/'
|| DB_NAME.value
|| '_ora_'
|| V$PROCESS.SPID
|| nvl2(V$PROCESS.TRACEID, '_' || V$PROCESS.TRACEID, null)
|| '.trc'
"Trace File"
from V$PARAMETER U_DUMP
cross join V$PARAMETER DB_NAME
cross join V$PROCESS
join V$SESSION
on V$PROCESS.ADDR = V$SESSION.PADDR
where U_DUMP.NAME = 'user_dump_dest'
and DB_NAME.NAME = 'db_name'
and v$session.audsid=sys_context('userenv','sessionid');
A dba at my company gave me this one. It's
CREATE OR REPLACE PROCEDURE "SYS"."DROP_SCHEMA_FAST" (pSchema IN
VARCHAR2)
IS
cnt NUMBER(5) := 0;
sql1 varchar2(4000);
x PLS_INTEGER;
--disable constraints:
cursor cur1 is select 'alter table ' || OWNER ||'.'||table_name||' disable constraint '||constraint_name sql2
from all_constraints where owner=pSchema and status='ENABLED'
and table_name not like 'BIN$%' and constraint_name not like 'SYS_%' and constraint_name not like '%PK%';
cursor cur2 is select 'alter table ' || OWNER ||'.'||table_name||' disable constraint '||constraint_name sql2
from all_constraints where owner=pSchema and status='ENABLED'
and table_name not like 'BIN$%' and constraint_name not like 'SYS_%';
--truncate all tables:
cursor cur3 is select 'truncate table ' || OWNER ||'.'||table_name sql2 from all_tables where owner=pSchema
and table_name not like 'BIN$%';
BEGIN
SELECT COUNT(*) INTO cnt FROM dba_users WHERE UPPER(username) = UPPER(pSchema);
IF (cnt <= 0) THEN
RETURN;
END IF;
sql1 := 'ALTER USER ' || UPPER(pSchema) || ' ACCOUNT LOCK';
EXECUTE IMMEDIATE sql1;
--disable constraints:
FOR ao_rec IN cur1 LOOP
EXECUTE IMMEDIATE ao_rec.sql2;
END LOOP;
FOR ao_rec IN cur2 LOOP
EXECUTE IMMEDIATE ao_rec.sql2;
END LOOP;
--truncate all tables:
FOR ao_rec IN cur3 LOOP
EXECUTE IMMEDIATE ao_rec.sql2;
END LOOP;
--drop schema:
sql1 := 'DROP USER ' || UPPER(pSchema) || ' CASCADE';
EXECUTE IMMEDIATE sql1;
exception when others then null;
END;
Also had this problem, got fixed by setting "PLScope identifiers:" to "None" in Tools->Preferences ->Database->PL/SQL Compiler
Is it possible to do direct-load INSERTs in Oracle through JDBC?
I currently use batched prepared statements (through Spring JDBC), is there any way to make these bypass the redo logs on a NOLOGGING table?
This is with Oracle 11g.
direct path inserts are only possible in a insert into x as select * from y scenario. This can be done using jdbc, no problem. This can not be done with insert and values. This also can not be done when the database in in force logging mode. Most of the times when a standby database in connected, the primary database will be in force logging mode.
As Gary Myers mentioned, since 11gR2 there is the APPEND_VALUES hint. As with the 'old' append hint, it should only be used for bulk inserts.
I hope this helps,
Ronald.
There is an APPEND_VALUES hint introduced in 11gR2 for direct path inserts with INSERT...VALUES.
Don't have an 11gR2 instance available to test whether it works with JDBC batch inserts. It is worth a try though.
I was able to use APPEND_VALUES hint with Oracle 12c with JDBC batching. I verified direct path insert happened via Oracle Enterprise manager where explain plan shows Load As Select
edit: I am not on the project anymore but I try to come up with more details:
The code was something like:
prepareTableForLargeInsert("TABLE_X")
preparedStatement = conn.prepareStatement("INSERT /*+ APPEND_VALUES */ INTO TABLE_X(A, B) VALUES(?,?)");
while(thereIsStuffToInsert()) {
for (ThingToWrite entity : getBatch()) {
int i = 1;
preparedStatement.setLong(i++, entity.getA());
preparedStatement.setString(i++, entity.getB());
...
}
preparedStatement.executeBatch();
preparedStatement.clearParameters();
}
repairTableAfterLargeInsert("TABLE_X")
One needs to verify whether direct path was really used (table is locked / conventional insert in same tx fails / actual execution plans shows Load As Select)
methods prepareTableForLargeInsert and repairTableAfterLargeInsert were calling stored procedures. They might be helpful:
PROCEDURE sp_before_large_insert (in_table_name IN VARCHAR2) AS
BEGIN
-- force parallel processing
EXECUTE IMMEDIATE 'ALTER SESSION FORCE PARALLEL DML';
EXECUTE IMMEDIATE 'ALTER SESSION FORCE PARALLEL QUERY';
EXECUTE IMMEDIATE 'ALTER SESSION FORCE PARALLEL DDL';
-- set table to NOLOGGING
EXECUTE IMMEDIATE 'ALTER TABLE ' || in_table_name || ' NOLOGGING';
-- disable all FK constraints referencing the table. all but those used for Partition by reference
FOR cur IN (SELECT a.owner, a.constraint_name, a.table_name
FROM all_cons_columns a
JOIN all_constraints c ON a.owner = c.owner
AND a.constraint_name = c.constraint_name
JOIN all_constraints c_pk ON c.r_owner = c_pk.owner
AND C.R_CONSTRAINT_NAME = C_PK.CONSTRAINT_NAME
LEFT JOIN user_part_tables pt on pt.ref_ptn_constraint_name = c.constraint_name
WHERE C.CONSTRAINT_TYPE = 'R'
AND pt.ref_ptn_constraint_name IS NULL
AND A.OWNER LIKE '%_OWNER'
AND c_pk.table_name = in_table_name)
LOOP
execute immediate 'ALTER TABLE "'||cur.owner||'"."'||cur.table_name||'" MODIFY CONSTRAINT "'||cur.constraint_name||'" DISABLE';
END LOOP;
-- disable FKs (but one used for Partition by reference), PK (unless referenced by enabled FK for partition reference) and UCs on table
FOR c IN (select distinct rc.CONSTRAINT_NAME FROM user_constraints rc
LEFT JOIN user_part_tables pt on pt.ref_ptn_constraint_name = rc.constraint_name
LEFT JOIN user_constraints c_fk ON c_fk.R_CONSTRAINT_NAME = rc.CONSTRAINT_NAME AND c_fk.status = 'ENABLED'
WHERE rc.owner like '%OWNER'
AND pt.ref_ptn_constraint_name IS NULL
AND c_fk.R_CONSTRAINT_NAME IS NULL
AND rc.CONSTRAINT_TYPE IN ('R', 'U', 'P')
AND rc.TABLE_NAME = in_table_name)
LOOP
EXECUTE IMMEDIATE 'ALTER TABLE ' || in_table_name || ' DISABLE CONSTRAINT ' || c.CONSTRAINT_NAME;
END LOOP;
-- set unusable non-local non-unique indexes on table
FOR c IN (select INDEX_NAME from all_indexes
where table_owner LIKE '%_OWNER'
and PARTITIONED = 'NO'
and UNIQUENESS = 'NONUNIQUE'
and STATUS = 'VALID'
and TABLE_NAME = in_table_name)
LOOP
EXECUTE IMMEDIATE 'ALTER INDEX ' || c.index_name || ' UNUSABLE';
END LOOP;
END sp_before_large_insert;
PROCEDURE sp_after_large_insert (in_table_name IN VARCHAR2) AS
BEGIN
-- rebuild disabled indexes on table
FOR c IN (select INDEX_NAME from all_indexes
where table_owner LIKE '%_OWNER'
and STATUS = 'UNUSABLE'
and TABLE_NAME = in_table_name)
LOOP
EXECUTE IMMEDIATE 'ALTER INDEX ' || c.index_name || ' REBUILD PARALLEL NOLOGGING';
END LOOP;
-- enable FKs, PK and UCs on table
FOR c IN (select CONSTRAINT_NAME, CONSTRAINT_TYPE
FROM user_constraints
WHERE owner like '%OWNER'
AND CONSTRAINT_TYPE IN ('R', 'U', 'P')
AND TABLE_NAME = in_table_name)
LOOP
IF c.CONSTRAINT_TYPE = 'P' THEN
EXECUTE IMMEDIATE 'ALTER TABLE ' || in_table_name || ' ENABLE CONSTRAINT ' || c.CONSTRAINT_NAME || ' USING INDEX REVERSE';
ELSE
EXECUTE IMMEDIATE 'ALTER TABLE ' || in_table_name || ' ENABLE CONSTRAINT ' || c.CONSTRAINT_NAME;
END IF;
END LOOP;
-- enable FKs constraints on related tables
FOR cur IN (select fk.owner, fk.constraint_name , fk.table_name
from all_constraints fk, all_constraints pk
where fk.CONSTRAINT_TYPE = 'R' and
pk.owner LIKE '%_OWNER' and
fk.r_owner = pk.owner and
fk.R_CONSTRAINT_NAME = pk.CONSTRAINT_NAME and
pk.TABLE_NAME = in_table_name)
LOOP
execute immediate 'ALTER TABLE "'||cur.owner||'"."'||cur.table_name||'" MODIFY CONSTRAINT "'||cur.constraint_name||'" ENABLE';
END LOOP;
-- set table to LOGGING
EXECUTE IMMEDIATE 'ALTER TABLE ' || in_table_name || ' LOGGING';
-- disable parallel processing
EXECUTE IMMEDIATE 'ALTER SESSION DISABLE PARALLEL DML';
EXECUTE IMMEDIATE 'ALTER SESSION DISABLE PARALLEL QUERY';
EXECUTE IMMEDIATE 'ALTER SESSION DISABLE PARALLEL DDL';
-- clean up indexes i.e. set logging and noparallel again
FOR c IN (SELECT INDEX_NAME FROM ALL_INDEXES
WHERE (TRIM(DEGREE) > TO_CHAR(1) OR LOGGING = 'NO')
AND OWNER LIKE '%_OWNER'
AND TABLE_NAME = in_table_name)
LOOP
EXECUTE IMMEDIATE 'ALTER INDEX ' || c.index_name || ' NOPARALLEL LOGGING';
END LOOP;
END sp_after_large_insert;
I recall there were issues with recreating tailored indexes for disabled UC e.g. because of losing the information how they were partitioned (global hash partitioned) (making the indexes just UNUSABLE doesn't work)
Notes:
when parallelizing to different threads one doesn't gain much as each of these thread is eventually serialized on the table lock
our table was partitioned. insert slow down was observed if batch writes to different partitions - good is to write to as little partitions as possible per batch
major speed up could be possibly achieved if each thread wrote to its own plain (temporary?) table and at the end these tables are 'coalesced' into the main table - but this was never tried out
Does
insert /*+ append */ into desttab select * from srctab
not work in JDBC ?
Use:
INSERT /*+ APPEND_VALUES */ INTO table_name (column1, column2) values (?,?);
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;