Why can't we drop a referenced Type unlike other schema objects - oracle

When a Type which is having dependents is tried to drop or replace, oracle throws below error. Unlike for the other schema objects (like procedures) where you drop an objects then it gets dropped and the dependent objects get invalid. My two questions are
1) Why is Typeso special that it prevents drop/replace when it has dependents.
2) What logic takes separates the above behavior for Type.
create
ORA-02303: cannot drop or replace a type with type or table dependents.

"Why is Type so special "
There are two differences between Types and Procedures.
Sub-types have an absolute dependency on their super-type. If a stored procedure has a dependency on a function and we delete that function the procedure is invalidated. But we can make the procedure valid simply by editing the code so it doesn't use the function. Whereas if we drop the super-type the sub-type is permanently invalidated; we cannot edit it to remove its dependence on the super-type, because the super-type defines it. Simply, the sub-type is inoperable until we re-create the super-type.
We can use a Type to declare database tables and table columns. Those are structures with persistent state: we can't invalidate a table column like a stored procedure, because of the data. If we drop a Type which is used by a database table we lose the data held in the Type structure.
There is syntax to drop a Type with dependencies without hurling ORA-02303:
drop type my_type force;
This renders all the sub-types invalid, and - more drastically - sets any dependent table columns as unused and invalidates any dependent tables. An unused table column is effectively dropped; its data is inaccessible. To recover an unused column (or invalidated table) requires a tablespace point-in-time recovery on an auxilliary instance, which is not a trivial undertaking. (That it is so easy to unwittingly render data irretrievable is one reason why object-relational tables are not a good idea.)

Related

In Oracle 19c database, when we drop a table what happens to the procedures, triggers, index that uses this table?

In Oracle 19c database, when we drop a table what happens to the procedures, triggers, index that uses this table?
Will the triggers, procedures, index gets dropped automatically or
will it become INVALID status?
I want to know what is the correct process that needs to be
followed while dropping the table when you know you already have
the triggers, procedures, index associated with that particular
table?
Please help me out.
Indexes and triggers on the table will be dropped (as will grants)
Synonyms and views will become invalid
Hard-coded references to the table in procedures, packages, functions and triggers will make them invalid. References via dynamic SQL won't result in invalidation, but would fail when executed.
Query the DBA_DEPENDENCIES view to see which objects have dependencies and will get invalidated. There can be knock on impacts (dropping a table invalidates a procedure and a package that calls that procedure will be invalidated even if it doesn't reference the table directly).
If all usages are within the same user/schema, you can query USER_DEPENDENCIES instead. Don't bother with ALL_DEPENDENCIES view as, if another user has created objects referencing the victim table, you might not have privileges to see that object anyway.

Oracle PL/SQL table of parent object type breaks when I add another inheriting child object type

I am using custom object types with Oracle PL/SQL, including several object types that inherit from a parent object. I have a TP_DOCUMENTS parent object, and child document types, such as TP_PUBLICATION, TP_CONTRACT, etc. We successfully created a table of TP_DOCUMENT and have added records of TP_PUBLICATION, TP_CONTRACT, and other child document records. However, I needed to create an additional type of document. Once I did this, it broke the DOCUMENTS table. How can I create additional child types, without breaking the table of the parent object (making me lose all the data previously contained in the parent object table!!)?
Here is some of my code:
create or replace TYPE "TP_DOCUMENT" AS OBJECT
(
...fields go here
) NOT FINAL
create or replace TYPE "TP_PUB_INSTRUCTION" UNDER TP_DOCUMENT()
CREATE TABLE DOCUMENTS OF TP_DOCUMENT
After creating these types (and others with additional fields), I created the table DOCUMENTs as shown above. I tried to create another sub-type, and the DOCUMENTS table broke.
MORE INFORMATION:
The error code message is as follows:
ORA-04063: table/view has errors
Cause: Attempt to execute a stored procedure or use a view that has errors. For stored procedures, the problem could be syntax errors or references to other, non-existent procedures. For views, the problem could be a reference in the view's defining query to a non-existent table. Can also be a table which has references to non-existent or inaccessible types.
Action: Fix the errors and/or create referenced objects as necessary.
Thank you!
UPDATE WITH ANSWER FROM COMMENTER BELOW:
I had unfortunately dropped a Sub-Type using the Force option. That likely was the cause for why my Documents table was corrupted. In the future, I will use the Validate command (see answer below).
Instead of FORCE you should use the VALIDATE option when dropping types:
VALIDATE
If you specify VALIDATE when dropping a type, then Oracle Database
checks for stored instances of this type within substitutable columns
of any of its supertypes. If no such instances are found, then the
database completes the drop operation.
This clause is meaningful only for subtypes. Oracle recommends the use
of this option to safely drop subtypes that do not have any explicit
type or table dependencies.
Here's an example:
create or replace type tp_document as object
(
a number
) not final;
create or replace type tp_pub_instruction under tp_document();
create table documents of tp_document;
--This fails with this error message:
--ORA-02303: cannot drop or replace a type with type or table dependents
drop type tp_pub_instruction;
--This works since there's no data with that type.
drop type tp_pub_instruction validate;

retrieve user defined datatype from table

SQL> -- CASE 1
SQL>select nest_test.id.num from nest_test;
select nest_test.id.num from nest_test
*
ERROR at line 1:
ORA-00904: "NEST_TEST"."ID"."NUM": invalid identifier
SQL> -- CASE 2
SQL>select n.id.num from nest_test n;
ID.NUM
----------
12
As, AFAIK, aliasing any table is just giving simple name to the table or column. Then, why I'm getting error in Case 1, when I'm trying to retrieve user defined object from table ? What actually happened, when I aliased my table.
The Oracle documentation states that table aliases are required to reference methods or attributes of objects to avoid the potential for "inner capture" (a table column name clashing with an object attribute name). Find out more.
The documentation states:
"You must qualify a reference to an object attribute or method with a table alias rather than a table name even if the table name is itself qualified by a schema name."
It doesn't say why Oracle enforce this rule. But there is obviously some complexity in the namespace implementation, caused by retrofitting objects into the relational kernel.
"then, why this query works select emp.sal from emp"
Because that's a regular column on a table. Oracle have never enforced aliases on normal tables. Starting now would break an enormous amount of code which has accrued over the decades.
Having to use aliases is just one more penalty for using object types to define table columns. It's far from being teh most onerous aspect of the clunky syntax which goes with Oracle's ORDBMS implementation.
Besides, there's almost cases in which using objects rather than realtional tables to persist data is the rigyht solution, so it doesn't really matter.

Can I drop/add attribute without consequences? Oracle Object Type

I have an OBJECT_TYPE with ATTRIBUTE varchar2(200). There many other objects referencing this one. I need to reduce the length of the attribute to varchar2(50). I know I cannot do it directly, so I found this way:
ALTER TYPE CUSTOMER DROP ATTRIBUTE name INVALIDATE;
ALTER TYPE CUSTOMER ADD ATTRIBUTE name varchar2(50) CASCADE;
The question is: is there anything that could be broken after the dropping/creating of the attribute? Is it correct to use the INVALIDATE option instead of CASCADE in the DROP statement? I don't want to loose anything - relations or data.
Is there a reason the following is not used:
ALTER TYPE CUSTOMER MODIFY ATTRIBUTE name VARCHAR2(50);
I have run into compatibility problems when using types and dropping an attribute especially if there are tables and data defined using the types. This is one reason I avoid basing tables and views on the data types. The change in the length would invalidate the table and any rows where the associated data exceeds 50. If the other objects are just types and are not used in views and tables then the alter type above should work fine. And you may need to recompile any types. Keep in mind that the type is becoming more restrictive and how it may affect any associated data.

Difference between object and record type

I am just curious whats the difference between object and record type in oracle, More specifically between the below declarations
create type emp2_oty is object
(
empno number,
ename varchar2(20),
deptno number
);
create type emp2_nt is table of emp2_oty;
and
type emp2_oty is record
(
empno number,
ename varchar2(20),
deptno number
);
create type emp2_nt is table of emp2_oty;
Please elaborate.
record:
Cannot be stored in the database.
Cannot be recursively referenced.
Cannot have logic defined as part of their definition.
object:
Can be stored as a database table column or as an entire row.
Can be recursively referenced using the SELF parameter.
Can have logic defined as part of their definition using member methods.
The OBJECT type can be stored in the database and can be used in both SQL and PL/SQL
Understanding PL/SQL Records
Records are composed of a group of fields, similar to the columns in a row.The %ROWTYPE attribute lets you declare a PL/SQL record that represents a row in a database table, without listing all the columns.
Basically, if you are familiar with C/C++ or similar languages, you could tell that Records are nothing but structures (i.e a data type that can be used to group items of possibly different types into a single type) they can not have methods within. Objects on the other hand are completely different:
Oracle Objects
Oracle object types are user-defined types that make it possible to model real-world entities
1. Objects Can Encapsulate Operations Along with Data
Database tables contain only data. Objects can include the ability to perform operations (i.e methods) that are likely to be needed on that data (e.g a purchase order object might include a method to sum the cost of all the items purchased).
2. Objects Can Represent Part-Whole Relationships
An object can have other objects as attributes, and the attribute objects can have their own object attributes too. An entire parts-list hierarchy can be built up in this way from interlocking object types.
3. Objects Are Efficient
3.1 Object types and their methods are stored with the data in the database, so they are available for any application to use.
3.2 You can fetch and manipulate a set of related objects as a single unit (e.g when you select a customer object and get the customer's name, phone, and the multiple parts of his address in a single round-trip between the client and the server) .

Resources