Does Oracle table drop also trigger dropping all its sequences? - spring

I have an oracle table called for example APP_TABLE having a sequence SEQ_TABLE. I want to drop a table with its sequence in a single command.
Note the sequence has been generated through Hibernate (is it a "system-generated" sequence?)
<generator class="native">
<param name="sequence">SEQ_TABLE</param>
</generator>
Does DROP TABLE APP_TABLE also trigger dropping its sequence in Oracle? I have searched in the documentation (I am using the 19c version) and I have learned all its indices and triggers are removed, but nothing about sequences (the information can be incomplete, though).
How to assure the underlying sequence is also removed without dropping it by explicitly finding out and performing a drop by its name?

If the sequence is genuinely 'part' of the table definition (in which case it is visibly linked in USER_TAB_IDENTITY_COLS) then it will be dropped. Otherwise it is an independent object and will remain.

You can make drop sql for the sequences you want to remove if they are used in the trigger.
select 'DROP SEQUENCE '||REFERENCED_OWNER||'.'||REFERENCED_NAME||' ;' from user_dependencies
where name in (select TRIGGER_NAME from user_triggers
where BASE_OBJECT_TYPE = 'TABLE'
and TABLE_NAME = 'NAME_OF_TABLE')
and referenced_type = 'SEQUENCE';

Related

How to remove a strange table named "BIN$c+eOnMB3RbKSEfg/rsxtAQ==$0" from oracle database?

I am new to Oracle and for practice I have created some tables (customer, drivers, payment, booking, location, area, job, job_history) in Oracle 11g and upon select * from cat statement I have found a strange table with other created tables named "BIN$c+eOnMB3RbKSEfg/rsxtAQ==$0".I don't know why this table is created.
I tried to remove this table through
drop table BIN$c+eOnMB3RbKSEfg/rsxtAQ==$0;
but it gives error:
drop table BIN$c+*eOnMB3RbKSEfg/rsxtAQ==$0
ERROR at line 1: ORA-00933: SQL command not properly ended
what should I do to remove it?
What you see is a deleted table in the RECYCLEBIN
You may get the original name of the table with this query
SELECT original_name FROM RECYCLEBIN where OBJECT_NAME = 'BIN$c+eOnMB3RbKSEfg/rsxtAQ==$0';
Note that (with your parameter setting) if you DROP a table it is not completely removed, but moved in the recyclebin.
You may ommit this using the PURGE option.
DROP TABLE xxx PURGE;
To remove the table from the recyclebin you must qoute the name with double quotes (as this is not a valid name) and use the PURGE statement (not a DROP - which would trigger ORA-38301: can not perform DDL/DML over objects in Recycle Bin).
PURGE TABLE "BIN$c+eOnMB3RbKSEfg/rsxtAQ==$0"
Alternatively you may use the original_name obtained with the query above:
PURGE TABLE {your_original_name};
To clean up the recyclebin completely use this statement (with the propper table user)
PURGE RECYCLEBIN;

oracle replace view during query

What happens if a view is replaced while a query that uses that view is running?
I guess that since a view is just a stored query, nothing will happen. When running a query that includes a view, the view is replaced by the actual query. Is that assumption correct?
Thanks
Since SQL cursor is open Oracle fetches all data from rollback segment. So even you drop table in another session your first session will continue to fetch rows from dropped table. Same for view.
I think currently-running queries will continue to run even if their underlying views are modified.
Do not confuse Data Definition Language (DDL) changes with the Oracle mantra "readers and writers do not block each other". The technology that prevents that blocking does not prevent DDL from interfering with queries. There most certainly are cases where a DDL statement can break a currently-running SQL statement.
The examples below demonstrate a TRUNCATE breaking a SELECT, and then demonstrate a similar CREATE OR REPLACE VIEW not breaking a SELECT.
Truncate interfering with currently-running query
--Session #1 - Create table and data.
drop table table1;
create table table1(a number);
insert into table1 select level from dual connect by level <= 100000;
commit;
--Session #2 - Query table. Use an IDE and only retrieve the first N rows.
select * from table1;
--Session #1 - Truncate table.
truncate table table1;
--Session #2: Retrieve the rest of the rows.
--This may be difficult to reproduce, and may depend on memory
--or other environment settings.
ORA-08103: object no longer exists
View change does not interfere with currently-running query
--Session #1 - Create table and data.
drop table table1;
create table table1(a number);
insert into table1 select level from dual connect by level <= 100000;
commit;
create or replace view view1 as select a from table1;
--Session #2 - Query table. Use an IDE and only retrieve the first N rows.
select * from view1;
--Session #1 - Create a new version of the view.
create or replace view view1 as select 1 a from table1;
--Session #2: Retrieve the rest of the rows.
All rows are returned with the original values.
Warnings
This is only a simple example, do not take this as proof that a SELECT is always immune to view changes. I'm not sure if you could ever prove that view changes don't interfere with SELECT. Your assumption that a view is initially replaced by the query makes sense but I'm not 100% sure it is accurate. Oracle has mechanisms to re-optimize queries in the middle of an execution, it's possible that one of those re-optimizations
can break something.
If you need to be certain this will work, here are some options:
Contact Oracle Support.
Offer a bounty for a counter-example. That still won't prove it's impossible but it certainly will increase your confidence.
Thoroughly test your application.

Oracle how to delete from a table except few partitions data

I have a big table with lot of data partitioned into multiple partitions. I want to keep a few partitions as they are but delete the rest of the data from the table. I tried searching for a similar question and couldn't find it in stackoverflow. What is the best way to write a query in Oracle to achieve the same?
It is easy to delete data from a specific partition: this statement clears down all the data for February 2012:
delete from t23 partition (feb2012);
A quicker method is to truncate the partition:
alter table t23 truncate partition feb2012;
There are two potential snags here:
Oracle won't let us truncate partitions if we have foreign keys referencing the table.
The operation invalidates any partitioned Indexes so we need to rebuild them afterwards.
Also, it's DDL, so no rollback.
If we never again want to store data for that month we can drop the partition:
alter table t23 drop partition feb2012;
The problem arises when we want to zap multiple partitions and we don't fancy all that typing. We cannot parameterise the partition name, because it's an object name not a variable (no quotes). So leave only dynamic SQL.
As you want to remove most of the data but retain the partition structure truncating the partitions is the best option. Remember to invalidate any integrity constraints (and to reinstate them afterwards).
declare
stmt varchar2(32767);
begin
for lrec in ( select partition_name
from user_tab_partitions
where table_name = 'T23'
and partition_name like '%2012'
)
loop
stmt := 'alter table t23 truncate partition '
|| lrec.partition_name
;
dbms_output.put_line(stmt);
execute immediate stmt;
end loop;
end;
/
You should definitely run the loop first with execute immediate call commented out, so you can see which partitions your WHERE clause is selecting. Obviously you have a back-up and can recover data you didn't mean to remove. But the quickest way to undertake a restore is not to need one.
Afterwards run this query to see which partitions you should rebuild:
select ip.index_name, ip.partition_name, ip.status
from user_indexes i
join user_ind_partitions ip
on ip.index_name = i.index_name
where i.table_name = 'T23'
and ip.status = 'UNUSABLE';
You can automate the rebuild statements in a similar fashion.
" I am thinking of copying the data of partitions I need into a temp
table and truncate the original table and copy back the data from temp
table to original table. "
That's another way of doing things. With exchange partition it might be quite quick. It might also be slower. It also depends on things like foreign keys and indexes, and the ratio of zapped partitions to retained ones. If performance is important and/or you need to undertake this operation regularly then you should to benchmark the various options and see what works best for you.
You must very be careful in drop partition from a partition table. Partition table usually used for big data tables and if (and only if) you have a global index on the table, drop partition make your global index invalid and you should rebuild your global index in a big table, this is disaster.
For minimum side effect for queries on the table in this scenario, I first delete records in the partition and make it empty partition, then with
ALTER TABLE table_name DROP PARTITION partition_name UPDATE GLOBAL INDEXES;
drop empty partition without make my global index invalid.

Enforcement of unique/primary key - drop index

I am trying to drop an index :
DROP INDEX PK_CHARGES
but I get this error
cannot drop index used for enforcement of unique/primary key
Why I am getting this error? I will provide further information if you need any.
How to solve it?
Edit I have no primary key in the table, but I found this weird index that I don't remember I had added:
index name = SYS_C0040476 which have the same columns
You can query the ALL_CONSTRAINTS performance view to see which constraint the index is used by, and which table it applies to, e.g:
select owner, constraint_name, constraint_type,
table_name, index_owner, index_name
from all_constraints
where index_name = 'PK_CHARGES';
I would expect the table name to be 'CHARGES', the constraint name to match the index name, and the constraint type to be 'P'. But since you have a table in mind, perhaps the names aren't following a helpful convention. Maybe an old version of the table was renamed, which would leave the constraints against the new name (e.g. CHARGES_BACKUP or something).
You said you click on the table, then on the view. Perhaps you're not looking at the table that the constraint/index is on; or perhaps you're looking at a view on top of the actual table. You also mention a SYS_ index on the same columns - which can't be on the same table. Do you have multiple similar tables, or access to multiple schemas? You shold run the above query for that index too. As mentions above, you might find an old version (or versions) of the table.
Once you've identified which table the constraint is on, you'll need to decide whether you should actually be keeping it, and if not you can remove it by dropping the constraint with an ALTER TABLE command.
The problem with
But I found this weird index that I dont rember I hadve add
comes because you didn't add it. You had a primary key, then you dropped it, but when you do that Oracle doesn't drop the associated unique index that every primary key has.
So when you drop a primary key you have to drop the unique index of that primary key, that amazingly has the same name as the primary key had.
So for dropping a MY_TABLE_PK you must do:
ALTER TABLE MY_TABLE DROP PRIMARY KEY DROP INDEX;
so you ensure that the index is dropped as well.
"from pl/sql I right click on the table"
The problem with IDEs is that they make us feel very productive, because we can do things with just a click instead of writing some code. This is a problem because when something unusual happens the IDE is no good for investigation and we lack the understanding of the underlying structure of the database which we need to help ourselves.
If you want to learn the Oracle database the worst thing you can do is download SQL Developer or PLSQL Developer or TOAD. They're all fine tools but the only people who should use them are the people who don't need to use them.
the following worked for me with unique index:
ALTER INDEX UX_CHARGES UNUSABLE
/
DROP INDEX UX_CHARGES
/
see: https://docs.oracle.com/cd/E18283_01/server.112/e17120/indexes004.htm#insertedID3

How can I drop a "not null" constraint in Oracle when I don't know the name of the constraint?

I have a database which has a NOT NULL constraint on a field, and I want to remove this constraint. The complicating factor is that this constraint has a system-defined name, and that constraint's name differs between the production server, integration server, and the various developer databases. Our current process is to check in change scripts, and an automated task executes the appropriate queries through sqlplus against the target database, so I'd prefer a solution that could just be sent straight into sqlplus.
On my own database, the SQL to drop this would be:
alter table MYTABLE drop constraint SYS_C0044566
I can see the constraint when I query the all_constraints view:
select * from all_constraints where table_name = 'MYTABLE'
but I am not sure how to work with the SEARCH_CONDITION's LONG data type or how best to dynamically delete the looked-up constraint even after I know its name.
So, how can I create a change script that can drop this constraint based on what it is, rather than what its name is?
EDIT:
#Allan's answer is a good one, but I am concerned (in my lack of Oracle expertise) that it may not be universally true that any constraint that might have a system-generated name will have associated with it a way to remove the constraint without having to know its name. Is it true that there will always be a way to avoid having to know a system-named constraint's name when logically dropping that constraint?
alter table MYTABLE modify (MYCOLUMN null);
In Oracle, not null constraints are created automatically when not null is specified for a column. Likewise, they are dropped automatically when the column is changed to allow nulls.
Clarifying the revised question: This solution only applies to constraints created for "not null" columns. If you specify "Primary Key" or a check constraint in the column definition without naming it, you'll end up with a system-generated name for the constraint (and the index, for the primary key). In those cases, you'd need to know the name to drop it. The best advice there is to avoid the scenario by making sure you specify a name for all constraints other than "not null". If you find yourself in the situation where you need to drop one of these constraints generically, you'll probably need to resort to PL/SQL and the data-definition tables.
Try:
alter table <your table> modify <column name> null;
Just remember, if the field you want to make nullable is part of a primary key, you can't.
Primary Keys cannot have null fields.
To discover any constraints used, use the code below:
-- Set the long data type for display purposes to 500000.
SET LONG 500000
-- Define a session scope variable.
VARIABLE output CLOB
-- Query the table definition through the <code>DBMS_METADATA</code> package.
SELECT dbms_metadata.get_ddl('TABLE','[Table Described]') INTO :output FROM dual;
This essentially shows a create statement for how the referenced table is made. By knowing how the table is created, you can see all of the table constraints.
Answer taken from Michael McLaughlin's blog: http://michaelmclaughlin.info/db1/lesson-5-querying-data/lab-5-querying-data/ From his Database Design I class.
I was facing the same problem trying to get around a custom check constraint that I needed to updated to allow different values. Problem is that ALL_CONSTRAINTS does't have a way to tell which column the constraint(s) are applied to. The way I managed to do it is by querying ALL_CONS_COLUMNS instead, then dropping each of the constraints by their name and recreate it.
select constraint_name
from all_cons_columns
where table_name = [TABLE_NAME]
and column_name = [COLUMN_NAME];
Something like that happened to me when I made copies of structures to temporary tables, so I removed the not null.
DECLARE
CURSOR cur_temp_not_null IS
SELECT table_name, constraint_name FROM all_constraints WHERE table_name LIKE 'TEMP_%' AND owner='myUSUARIO';
V_sql VARCHAR2(200);
BEGIN
FOR c_not_null IN cur_temp_not_null
LOOP
v_sql :='ALTER TABLE ' || c_not_null.table_name || ' DROP CONSTRAINT '|| c_not_null.constraint_name;
EXECUTE IMMEDIATE v_sql;
END LOOP;
END;
If constraint on column STATUS was created without a name during creating a table, Oracle will assign a random name for it. Unfortunately, we cannot modify the constraint directly.
Steps involved of dropping unnamed constraint linked to column STATUS
Duplicate STATUS field into a new field STATUS2
Define CHECK constraints on STATUS2
Migrate data from STATUS into STATUS2
Drop STATUS column
Rename STATUS2 to STATUS
ALTER TABLE MY_TABLE ADD STATUS2 NVARCHAR2(10) DEFAULT 'OPEN';
ALTER TABLE MY_TABLE ADD CONSTRAINT MY_TABLE_CHECK_STATUS CHECK (STATUS2 IN ('OPEN', 'CLOSED'));
UPDATE MY_TABLE SET STATUS2 = STATUS;
ALTER TABLE MY_TABLE DROP COLUMN STATUS;
ALTER TABLE MY_TABLE RENAME COLUMN STATUS2 TO STATUS;

Resources