What are nested table objects in Oracle? - oracle

Can someone explain what nested table objects are in Oracle ? While building an interface between to systems I discovered what was to me an odd column SYS_NC00054$. After some research I discovered that it was a nested table object from the function based index I created.

Function-based indexes are different from nested tables.
A regular index is built against actual columns ...
create index emp_job_idx on emp (job)
/
... whereas a function-based index is build on functions applied to columns. For instance we might what an index we can use when we query a date column without the time element...
create index emp_hire_idx on emp(trunc(hiredate))
/
When we query USER_IND_COLUMNS, the indexed column shows up in the first case but not in the second, because we are not indexing an actual column. What we see instead is the system generated "column'....
SQL> select index_name, column_name
2 from user_ind_columns
3 where table_name = 'EMP'
4 /
INDEX_NAME COLUMN_NAME
------------------------------ ---------------
PK_EMP EMPNO
EMP_UK ENAME
EMP_JOB_IDX JOB
EMP_HIRE_IDX SYS_NC00010$
SQL>
We can see the make-up of the index in USER_IND_EXPRESSIONS ...
SQL> select index_name, column_expression
2 from user_ind_expressions
3 where table_name = 'EMP'
4 /
INDEX_NAME COLUMN_EXPRESSION
------------------------------ --------------------
EMP_HIRE_IDC TRUNC("HIREDATE")
SQL>
Nested Tables
Nested tables are something different: they are user-defined arrays of simple or complex types. They can be used to define PL/SQL collections or columns in an ORDBMS table. Like this...
SQL> create or replace type address_t
2 as object
3 (
4 address_line_1 varchar2(70)
5 , address_line_2 varchar2(70)
6 , address_line_3 varchar2(70)
7 , address_line_4 varchar2(70)
8 , address_line_5 varchar2(70)
9 , postcode postcodestructure
10 ) final;
11 /
create or replace type address_t
*
ERROR at line 1:
ORA-02303: cannot drop or replace a type with type or table dependents
SQL>
SQL> create or replace type address_nt as table of address_t
2 /
Type created.
SQL>
SQL> create table contact_details (
2 person_id number not null
3 , email_address varchar2(254)
4 , addresses address_nt
5 )
6 nested table addresses store as nested_addresses
7 /
Table created.
SQL>

Basically, a table that has a column that stores data in the form of another table (or other complex type): A table nested inside another.
http://www.databasejournal.com/features/oracle/article.php/3788331/So-what-is-an-Oracle-Nested-Table.htm

Related

adding a sequence to an existing table

i created a table but i forgot to add a sequence to one of the PK, its a sequence on a form page, i just cant find anything about it, is it possible or do i have to do the form all over again.
i tried to replace the PK but it doesnt give me the option to add the sequence when creating a new one.
i searched everywhere and asked the support in chat (didn't really help since its not their job).
all i could find was this and this.
I'd suggest you to skip Apex in this matter and do the following: presume this is your table:
SQL> create table test
2 (id number constraint pk_test primary key,
3 name varchar2(20)
4 );
Table created.
This is the sequence:
SQL> create sequence myseq;
Sequence created.
As you forgot to specify PK source while creating Apex Form page, never mind - let the database handle it. How? Create a BEFORE INSERT trigger:
SQL> create or replace trigger trg_bi_test
2 before insert on test
3 for each row
4 when (new.id is null)
5 begin
6 :new.id := myseq.nextval;
7 end trg_bi_test;
8 /
Trigger created.
Let's test it: I'm inserting only the NAME (which is what your Apex Form will be doing):
SQL> insert into test (name) values ('Littlefoot');
1 row created.
What is table's contents?
SQL> select * from test;
ID NAME
---------- --------------------
1 Littlefoot
SQL>
See? Trigger automatically inserted ID (primary key) column value.
If it were an Interactive Grid (which lets you insert several records at a time):
SQL> insert into test (name)
2 select 'Bigfoot' from dual union all
3 select 'FAD' from dual;
2 rows created.
SQL> select * from test;
ID NAME
---------- --------------------
1 Littlefoot
2 Bigfoot
3 FAD
SQL>
Works just fine.
And what's another benefit: you don't have to modify Apex application at all.

select from the table name values after _ using oracle sql

Suppose if the table name is ABC_XYZ_123. I want to extract the integer values after _.
The output should be integer values after _.
In the above case, the output should be 123.
I have used the below sql query.
select from table_name like 'XXX_%';
But I am not getting required output. Can anyone help me with this query.
Thanks
Using REGEXP_SUBSTR with a capture group we can try:
SELECT REGEXP_SUBSTR(name, '_(\d+)$', 1, 1, NULL, 1)
FROM yourTable;
The question is somewhat unclear:
it looks as if you're looking for table names that contain number at the end, while
query you posted suggests that you're trying to select those numbers from one of table's columns
I'll stick to
Suppose if the table name is ABC_XYZ_123
If that's so, it is the data dictionary you'll query. USER_TABLES contains that information.
Let's create that table:
SQL> create table abc_xyz_123 (id number);
Table created.
Query selects numbers at the end of table names, for all my tables that end with numbers.
SQL> select table_name,
2 regexp_substr(table_name, '\d+$') result
3 from user_tables
4 where regexp_like(table_name, '\d+$');
TABLE_NAME RESULT
-------------------- ----------
TABLE1 1
TABLE2 2
restore_point-001 001
ABC_XYZ_123 123 --> here's your table
SQL>
Apparently, I have a few of them.

How should I use an object type in an insert DML statement?

I have created two TYPE objects to try out OOP processing in PL/SQL.
I tried to use my type o_customers in my INSERT statement, but I could not do it.
There is a Customers table. It has same columns as o_customers.
create or replace type o_customers as object (
id number,
name varchar2(40),
age number,
address o_addressC,
salary number
);
create or replace type o_addressC as object (
mahalle varchar(30),
apartman varchar(15),
ilce varchar(15),
apt_no number
);
declare
adres o_addressC;
musteri o_customers;
begin
adres := o_addressC('selami ali mah','çınar apt',' üsküdar',19);
musteri:= o_customers(10,'UĞUR SİNAN SAĞIROĞLU',26,adres,1000);
insert into customers values (musteri);
end;
" There is a customers table. it has same columns with o_customers"
In OOP it is not enough for objects to have the same structure to be compatible in a programming context: they must be the same type, or related to each other through inheritance.
So you need to create the table using that type:
SQL> create table customers of o_customers
2 /
Table created.
SQL> desc customers
Name Null? Type
---------------------- -------- -------------
ID NUMBER
NAME VARCHAR2(40)
AGE NUMBER
ADDRESS O_ADDRESSC
SALARY NUMBER
SQL>
Now your insert statement will work:
SQL> declare
2 adres o_addressC;
3 musteri o_customers;
4 begin
5 adres := o_addressC('selami ali mah','cınar apt','uskudar',19);
6 musteri:= o_customers(10,'UĞUR SİNAN SAĞIROĞLU',26,adres,1000);
7 insert into customers values(musteri);
8 end;
9 /
PL/SQL procedure successfully completed.
SQL> select * from customers;
ID NAME AGE
---------- ---------------------------------------- ----------
ADDRESS(MAHALLE, APARTMAN, ILCE, APT_NO)
------------------------------------------------------------------------------------------------------------------------------------------------------
SALARY
----------
10 UĞUR SİNAN SAĞIROĞLU 26
O_ADDRESSC('selami ali mah', 'c??nar apt', ' uskudar', 19)
1000
SQL>
Incidentally I had to make minor changes to the inserted values because the posted statement hurled
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 6
This is because your o_addressC type attributes are too small for strings with multi-byte characters.
Unless customers is an object table (create table customers of o_customers), you'll need to refer to the object's properties explicitly:
insert into customers
( id, name, age, address, salary)
values
( musteri.id, musteri.name, musteri.age, musteri.address, musteri.salary );
By the way, o_customer (no 's') would make more sense than o_customers for an object name.

Setting the primary key of a object type table in Oracle

I have two Oracle questions.
How can I set the primary key of a table when the table is made up of an object type? e.g.
CREATE TABLE object_names OF object_type
I have created a Varray type,
CREATE TYPE MULTI_TAG AS VARRAY(10) OF VARCHAR(10);
but when I try to do
SELECT p.tags.count FROM pg_photos p;
I get an invalid identifier error on the "count" part. p.tags is a MULTI_TAG, how can I get the number of elements in the MULTI_TAG?
First of all I wouldn't recommend storing data in Object tables. Objects are a great programmatic tool but querying Object tables leads to complicated SQL. I would advise storing your data in a standard relationnal model and using the objects in your procedures.
Now to answer your questions:
A primary key should be immutable, so most of the time an Object type is inappropriate for a primary key. You should define a surrogate key to reference your object.
You will have to convert the varray into a table to be able to query it from SQL
For example:
SQL> CREATE TYPE MULTI_TAG AS VARRAY(10) OF VARCHAR(10);
2 /
Type created
SQL> CREATE TABLE pg_photos (ID number, tags multi_tag);
Table created
SQL> INSERT INTO pg_photos VALUES (1, multi_tag('a','b','c'));
1 row inserted
SQL> INSERT INTO pg_photos VALUES (2, multi_tag('e','f','g'));
1 row inserted
SQL> SELECT p.id, COUNT(*)
2 FROM pg_photos p
3 CROSS JOIN TABLE(p.tags)
4 GROUP BY p.id;
ID COUNT(*)
---------- ----------
1 3
2 3
1)
A primary key is a constraint, to add constrains on object tables check this link:
http://download-west.oracle.com/docs/cd/B28359_01/appdev.111/b28371/adobjdes.htm#i452285
2)
The COUNT method can't be used in a SQL statement:
REF LINK IN COMMENTS
So in my case I had to do
SELECT p.pid AS pid, count(*) AS num_tags FROM pg_photos p, TABLE(p.tags) t2 GROUP BY p.pid;

Subtype Supertype with Oracle Object Type Creation. Limit on the number of subtypes?

I have run into an issue when creating a object type in Oracle 10g that inherits from a supertype. We currently have many object types that inherit from this supertype and recently the compiler started throwing the following errors
ORA-30745: error occured while trying to add column "SYS_NC_ROWINFO$" in table "DATA_CACHE.CACHE_ENTRIES"
ORA-01792: maximum number of columns in a table or view is 1000
Is there a cap on the number of subtypes you can generate that inherit from a supertype?
When you create tables with columns based on user-defined types, Oracle creates additional "secret" columns for you under the covers. For example:
SQL> create type emp_data_t as object (empno number, ename varchar2(30));
2 /
Type created.
SQL> create table emp_data_table (id int, emp_data emp_data_t);
Table created.
This table appears to have 2 columns:
SQL> desc emp_data_table
Name Null? Type
-------------------------- -------- ------------------------
ID NUMBER(38)
EMP_DATA EMP_DATA_T
... but it really has four:
SQL> select name
2 from sys.col$
3 where obj# = (select object_id
4 from user_objects
5 where object_name='EMP_DATA_TABLE');
NAME
------------------------------
ID
EMP_DATA
SYS_NC00003$
SYS_NC00004$
As you have seen, Oracle has a limit of 1000 columns per table. This limit will include any of these hidden columns derived from types and supertypes. It looks like your table has exceeded this limit.
use command:
PURGE RECYCLEBIN;

Resources