Oracle Associative arrays, how to define? - oracle

I am trying to create an associative array in Oracle, when I create a nested table, it works fine:
CREATE OR REPLACE TYPE TRNG_BOOK_AUTHORS_TAB
AS TABLE OF VARCHAR2(500);
But when I add the index I get errors:
CREATE OR REPLACE TYPE TRNG_BOOK_AUTHORS_TAB
AS TABLE OF VARCHAR2(500) INDEX BY PLS_INTEGER;
Error: PL/SQL: Compilation unit analysis terminated
Error(2,4): PLS-00355: use of pl/sql table not allowed in this context
What do I have wrong?

You are creating a schema type; those can be nested tables or varying arrays (varrays), but not associative arrays.
From the documentation for the create type statement:
A standalone collection type that you create with the CREATE TYPE statement differs from a collection type that you define with the keyword TYPE in a PL/SQL block or package. For information about the latter, see "Collection Variable Declaration".
With the CREATE TYPE statement, you can create nested table and VARRAY types, but not associative arrays. In a PL/SQL block or package, you can define all three collection types.

Related

PL/SQL Record and Table Variables inchanged

I am new to Oracle PL/SQL and have been given some code I am being asked to modify. I have been looking through the oracle documentation and think I know what it is doing but would like to get a verification as to if my understanding is correct or not.
Here is the code:
TYPE array_rec_type IS RECORD (gla_sub tblName.id%type);
v_closes_sc array_rec_type;
TYPE v_sc_type is TABLE OF v_closes_sc%TYPE INDEX BY BINARY_INTEGER;
sc_array v_sc_type;
Here is what I believe is being declared here:
TYPE array_rec_type IS RECORD (gla_sub tblName.id%type);
It looks like a collection is being declared using the column type from the id column from the tblName table. Which could be a number or UUID, etc.
v_closes_sc array_rec_type;
A variable of the newly created type is being created
TYPE v_sc_type is TABLE OF v_closes_sc%TYPE INDEX BY BINARY_INTEGER;
A new type is being created using the collection (Record) previously created a template for the table. The table will have a single column of ID.
sc_array v_sc_type;
A new variable is being created to hold the new table variable.
A record is not a collection, so your explanation is slightly confused. From the docs (which you've probably already looked at:
In a collection, the internal components always have the same data type, and are called elements. ... To create a collection variable, you either define a collection type and then create a variable of that type or use %TYPE.
In a record, the internal components can have different data types, and are called fields. You can access each field of a record variable by its name ... To create a record variable, you either define a RECORD type and then create a variable of that type or use %ROWTYPE or %TYPE.
So looking at what you said:
Here is what I believe is being declared here:
TYPE array_rec_type IS RECORD (gla_sub tblName.id%type);
This is a record, not a collection. In this case it has a single field called gla_sub which is indeed being declared using the data type of the id column from the tblName table. The use of %type means that, to some extent, you don't need to know what the data type actually is, and you may not have to change your code if that changes (if the size of a varchar2 column is increased, for instance).
v_closes_sc array_rec_type;
Correct - a variable of the newly created type is being created.
TYPE v_sc_type is TABLE OF v_closes_sc%TYPE INDEX BY BINARY_INTEGER;
This is a collection, specifically an associative array. It's a sparse array whose members are instance of the record type declared above, with a numeric index. That could also be declared using the type directly, as:
TYPE v_sc_type is TABLE OF array_rec_type INDEX BY BINARY_INTEGER;
sc_array v_sc_type;
Correct - a new variable is being created of that just-declared table type.
Having a record type with a single field seems a bit pointless, as you could have a collection based on the table column data type. Your existing code will be expecting that structure though, so changing it isn't quite trivial.

Difference between TABLE and PL/SQL TABLE in ALL_ARGUMENTS view

While fetching data by query
select * from ALL_ARGUMENTS
It will return two types in DATA_TYPE column
1- TABLE
2- PL/SQL TABLE
I have checked through containing procedure, both types are declared in a similar way.
What is the difference between them?
Example -
Have declaration
TYPE Bom_Revision_Tbl_Type IS TABLE OF Bom_Revision_Rec_Type - PL/SQl TABLE
OBJECT_NAME PKG NAME ARGUMENT_NAME DATA_TYPE
PROCESS_BOM BOM_BO_PUB P_BOM_REVISION_TBL PL/SQL TABLE
TYPE inv_ebi_name_value_pair_tbl IS TABLE OF inv_ebi_name_value_pair_rec - SQL TABLE
OBJECT_NAME PKG NAME ARGUMENT_NAME DATA_TYPE
ID_TO_VALUE INV_EBI_ITEM_HELPER P_PK_COL_NAME_VAL_PAIRS TABLE
There are three collection types in PL/SQL.
Your Bom_Revision_Tbl_Type is an associative array:
An associative array (formerly called PL/SQL table or index-by table) is a set of key-value pairs. Each key is a unique index, used to locate the associated value with the syntax variable_name(index).
It's defined with an index by clause. That is still reported in all_arguments as a "PL/SQL table", using the old name for that collection type.
Your inv_ebi_name_value_pair_tbl type is a nested table.
The documentation explains the differences between them, and when each type is appropriate; associative arrays:
An associative array is appropriate for:
A relatively small lookup table, which can be constructed in memory each time you invoke the subprogram or initialize the package that declares it
Passing collections to and from the database server
and nested tables:
A nested table is appropriate when:
The number of elements is not set.
Index values are not consecutive.
You must delete or update some elements, but not all elements simultaneously.
Nested table data is stored in a separate store table, a system-generated database table. When you access a nested table, the database joins the nested table with its store table. This makes nested tables suitable for queries and updates that affect only some elements of the collection.
You would create a separate lookup table, with multiple entries for each row of the main table, and access it through join queries.

Table types with dba objects

Why can't we create an object with the below code.
create or replace type typ_obj_dba_test as object (name_col
dba_objects.object_name%type);
It gives me object_name must be declared.
Is it because dba_objects is a view?
"Is it because dba_objects is a view?"
No. You couldn't do it with a table column either. The %TYPE syntax is restricted to PL/SQL and you are creating a SQL TYPE, not PL/SQL.
This restriction is annoying to many developers, particularly those coming from a background in more dynamic programming languages. But the snag is %TYPE syntax is dynamic: if the referenced column changes its data type the referencing object changes.
That's neat when we're declaring variables or parameters in stored procedures. But we can use SQL types to define table columns (*). Cascading a change in one column to who-knows-how-many columns which reference it would be a nightmare. So Oracle doesn't allow us to do it.
I'm afraid you'll need to use an explicit datatype declaration:
create or replace type typ_obj_dba_test as object (
name_col varchar2(30)
);
(*) It's not generally advisable to use Types in table definitions, but Oracle supports ORDBMS data structures.

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;

OOP concepts in oracle 11.g

i have a question related to Object Orienting programming in oracle database(11.g),generally i have studyed how to create object types or how to create table from existing object,but i am stoped on one topic,namely,suppose that we have created following type
create or replace type mono.Item_type as object(
item_id integer,
part REF mono.Part_type,
quantity integer);
where Part_type is already existed object type.
i know that i can create table from this object like this:
create table tablename of Item_type,for instance
create table item_list of Item_type
what what would be different,if instead of this,we use
create or replace type mono.Item_List as table of Item_type;
here inspite of this,that we use type keyword,we are creating table again and what is different between create table tablename of Item_type and
create or replace type mono.Item_List as table of Item_type;?
When you use create table tablename of Item_type, you're creating a table in the DB.
This table is a structure that can be used to store user's data .
When you use create or replace type mono.Item_List as table you're defining a new Datatype (similar to array).
This Datatype can be used as a type of a column in a DB table or as a type of a variable in plsql code.

Resources