Oracle object relational DB: Access columns of referenced rows - sql

I have some tables and need to create object views on top of them.
CREATE TABLE Person (
Nr NUMBER(4) PRIMARY KEY,
Name VARCHAR2(15));
CREATE TABLE Professor (
Nr NUMBER(4) PRIMARY KEY,
HabilThema VARCHAR2(30));
I also created types:
CREATE OR REPLACE TYPE Person_Typ AS OBJECT(
Nr INTEGER,
Name VARCHAR2(15)
);
CREATE OR REPLACE TYPE Professor_Typ AS OBJECT(
Nr INTEGER,
Habilthema VARCHAR2(30),
Person REF Person_Typ
);
As you can see there is a reference from a professor row to a person row. The view of the professors now should also include the columns of the person. Something like:
CREATE VIEW People OF Person_Typ
WITH OBJECT IDENTIFIER(Nr) AS
SELECT p.Nr, p.Name FROM Person p;
CREATE VIEW Professors OF Professor_Typ
WITH OBJECT IDENTIFIER(Nr) AS
SELECT p.Nr, p.Habilthema, p.Person.Name, MAKE_REF(People,p.Nr) FROM Professor p;
^
|_ Name of professor from Person table
But this does not work:
"P"."PERSON"."NAME" invalid identifier
Can this even be achieved by an object view? How?

Related

Can I change an attribute name from a table derived from a type?

Folowing the Object-Relational Database model, I wanted to create the tables or_doctor and or_recepcionist derived from the type t_employee.
Here, follows the type structure:
DROP TYPE t_employee FORCE;
CREATE OR REPLACE TYPE t_employee AS OBJECT (
num_employee INTEGER,
name_employee VARCHAR2(50),
birthdate_employee DATE
);
And here, the tables' structure:
DROP TABLE or_doctor CASCADE CONSTRAINTS;
CREATE TABLE or_doctor OF t_employee (
PRIMARY KEY (num_employee),
name_employee NOT NULL,
birthdate_employee NOT NULL
) OBJECT IDENTIFIER IS SYSTEM GENERATED;
DROP TABLE or_recepcionist CASCADE CONSTRAINTS;
CREATE TABLE or_recepcionist OF t_employee (
PRIMARY KEY (num_employee),
name_employee NOT NULL,
birthdate_employee NOT NULL
) OBJECT IDENTIFIER IS SYSTEM GENERATED;
Doing so, the attributes names, on both tables, will end up with "employee". Could I change the attribute name so they are specific in each table at the moment I'm creating the table?
E.G.:
Table or_doctor: num_doct, name_doct, birthdate_doct.
Table or_recepcionist: num_recep, name_recep, birthdate_recep.
As a frame challenge, don't add a suffix to your identifiers then you don't need to worry about the suffix being incorrect:
CREATE TYPE t_employee AS OBJECT (
num INTEGER,
name VARCHAR2(50),
birthdate DATE
);
CREATE TABLE or_doctor OF t_employee (
PRIMARY KEY (num),
name NOT NULL,
birthdate NOT NULL
) OBJECT IDENTIFIER IS SYSTEM GENERATED;
CREATE TABLE or_receptionist OF t_employee (
PRIMARY KEY (num),
name NOT NULL,
birthdate NOT NULL
) OBJECT IDENTIFIER IS SYSTEM GENERATED;
If you try to rename the column:
ALTER TABLE or_doctor RENAME COLUMN name TO name_doctor;
Then you will get the error:
ORA-23291: Only base table columns may be renamed
If you are using object-derived tables then you appear to be stuck with the identifiers from the object; so, make the object names generic so that they are appropriate in every place they are going to be used.

SuperType Table of subtype objects not showing added attributes

I am trying to make a supertype table of objects that holds subtype objects, but the bottom line insert once ran shows the first two attributes SSN and name as inserted. Is Oracle Express just broken these days? or is there something wrong in my code?
create or replace type PersonType as object (
SSN number (9),
name varchar2(30))
Instantiable
NOT Final;
create or replace type TenantType under PersonType (
aptNum REF ApartmentType,
phone number(10),
car varchar2(15),
contract varchar2(10));
Instantiable
Final;
create or replace type EmployeeType under PersonType (
empId number(4),
empAdr varchar2(40));
Instantiable
Final;
create table P1 of PersonType (
constraint P1_SSN_pk Primary Key (SSN));
insert into P1 values(TenantType(956785252, 'Jerry Wilson', (select ref(a) from A1 a where aptNum = 110), 8015167895, 'Toyota', '8 months'));
If you run simple select you see common values of supertype. When creating types you can add member function to display subtypes in different ways or you can use treat():
select treat(value(p) as tenanttype) from p1 p where p.ssn = 956785252
You have typos (unnecessary semicolons in type definitions) and missing definition of ApartmentType and table a1, so here are my test data: dbfiddle
And here are examples of mentioned member function show(): Inheritance in SQL Object Types

Using joins in complex queries

I have three tables customer_cars, bookings, and replaced_parts ad below:
CREATE TABLE customer_cars(
pk_car_id NUMBER(11) NOT NULL,
car_plate_number VARCHAR2(15) NOT NULL
);
CREATE TABLE bookings(
pk_booking_id NUMBER(11),
fk_car_id NUMBER(11),
);
CREATE TABLE replaced_parts(
pk_parts_id VARCHAR2(25),
fk_booking_id NUMBER(11),
replaced_parts parts_varray_type
);
CREATE OR REPLACE TYPE parts_type AS OBJECT (
name VARCHAR2(25),
price NUMBER(10),
);
/
CREATE TYPE parts_varray_type AS
VARRAY(40) OF parts_type;
/
I am trying to get parts name from parts_varray_type of a car. All i have is car_plate_number. Using this plate number i want to find pk_car_id in customer_cars and then that pk_car_if id should match with fk_car_id in bookings to find bookings_id. Then the found booking id should match with fk_booking_id in replaced_parts to get the parts_name.
INSERT INTO customer_cars (pk_car_id, car_plate_number)
VALUES(200000,'5651L');
INSERT INTO bookings(pk_booking_id, fk_car_id)
VALUES(700000,200000);
INSERT INTO replaced_parts (pk_parts_id, fk_booking_id, replaced_parts)
VALUES(700000,600000,
parts_varray_type(
parts_type('CLUTCH', 2000)));
Above is the insert statements. Now using plate number '5651L' i want to display clutch , 2000 from parts parray type.
Something like:
SELECT..
FROM..(Usings joins or any other methods)
WHERE pk_car_id = '5651L';
It should display name and price from parts varray type.

How to CREATE TABLE with disjoint relationship in SQL

I am trying to create a table using a disjoint subtype relationship.
For example, if the Supertype is furniture, and I have 3 Subtypes of furniture: chair, couch, and table.
Then:
CREATE TABLE Furniture
(order_num NUMBER(15), desc VARCHAR2(20), type VARCHAR2(10));
How do I make an option to pick type of chair, couch or table?
You can use REFERENCES in the CREATE TABLE.
CREATE TABLE Furniture_SubTypes
(
sub_type VARCHAR(10) PRIMARY KEY
);
INSERT INTO Furniture_SubTypes VALUES ('Chair');
INSERT INTO Furniture_SubTypes VALUES ('Couch');
INSERT INTO Furniture_SubTypes VALUES ('Table');
CREATE TABLE Furniture
(
order_num NUMBER,
description VARCHAR(20),
sub_type REFERENCES Furniture_SubTypes(sub_type)
);
Use a check constraint:
CREATE TABLE Furniture (
order_num NUMBER(15),
description VARCHAR2(20),
type VARCHAR2(10),
check (type in ('chair', 'couch', 'table'))
);
Note that desc is a poor choice for a column name, because it is a keyword in SQL (used for order by).

SQL Oracle Inheritance Relational Database

Here is an image:
This is how far I gone into coding:
CREATE TYPE appointment_list_type AS TABLE OF REF appointment_type;
/
CREATE OR REPLACE TYPE person_type AS OBJECT (
personID NUMBER,
Surname varchar2(10),
Forname varchar2(10),
dateOfBirth date,
AddressLine1 varchar2(30),
AddressLine2 varchar2(30),
Town varchar2(10),
contacTel1 varchar2(10),
contacTel2 varchar2(10)) NOT FINAL;
/
CREATE TYPE applicant_type UNDER person_type(
applicantID NUMBER,
maxPrice number(7,2),
desiredArea varchar2(10),
Attends appointment_list_type
);
/
CREATE TYPE salesperson_type UNDER person_type(
salespersonID NUMBER,
manager varchar2(10),
Makes appointment_list_type
);
/
This is creating the types of person seperating it into inheritance of Salesperson and Applicant.
CREATE TYPE appointment_type AS OBJECT(
appointmentID NUMBER,
Appdate date,
Apptime timestamp,
appointmentType varchar2(10),
levelOfInterest varchar2(10),
offerMade varchar2(10),
Made_by REF salesperson_type,
Attends_by REF applicant_type
);
/
This is appointment type, The references work for relating them together.
For creating the table:
CREATE TABLE person_table OF person_type (
personID PRIMARY KEY NOT NULL)
NESTED TABLE Attends STORE AS attend_meeting_table;
CREATE TABLE applicant_table OF applicant_type (
personID PRIMARY KEY NOT NULL)
NESTED TABLE Attends STORE AS attend_meeting_table;
CREATE TABLE salesperson_table OF salesperson_type (
personID PRIMARY KEY NOT NULL)
NESTED TABLE Makes STORE AS makes_meeting_table;
CREATE TABLE appointment_table OF appointment_type (
appointmentID PRIMARY KEY NOT NULL,
SCOPE FOR (Made_by) IS person_table,
SCOPE FOR (Attends_by) IS person_table);
Also here is some code of what I done, I now here is my question:
How does inheritance work with doing 1 to many directly into Appointment?
I am realy confused by this. Can anyone out me help me on how to do this?
phuh, I think I finally figured whats bothering you...
Currently, the appointments REFd in applicant_table and salesperson_table are totally independent. That means that applicants could come to meetings with sales persons that are actually in a meeting with someone else :)
Of course you want all appointments to be stored in appointment_table.
That is the perfect use case for object views. You do not need these object tables at all. Relational tables are much easier to manage.
Just create normal tables and then object views, just like this one for SALESPERSON:
create view ov_salesperson as
(select personID,
salespersonID,
SALESPERSON_TYPE
(personID
Surname,
Forname,
dateOfBirth,
AddressLine1,
AddressLine2,
Town,
contacTel1,
contacTel2,
salespersonID,
manager,
CAST
(MULTISET
(Select appointment_type
(appointmentID,
Appdate,
Apptime,
appointmentType,
levelOfInterest,
offerMade,
salesperson_id,
applicant_id
)
From appointment_table A
Where A.salesperson_id = S.salesperson_id
)
as appointment_list_type
)
) as salesperson_obj
from salesperson_table S
);