Inserting a ref value into an object table - sql

I have an assignment for college and I'm having trouble doing one of my inserts.
I have created an object called memeber
CREATE TYPE memeber AS OBJECT
(
member_id INTEGER,
member_name VARCHAR(30),
member_jobtitle VARCHAR(30),
member_skills skills_list,
past_projects past_projects_NTT
)
Then I created this object table
CREATE TABLE project_resources of MEMEBER
(
MEMBER_ID PRIMARY KEY,
MEMBER_NAME NOT NULL
)NESTED TABLE past_projects STORE AS PROJ_EXT;
Then I had to create an object called project as follows
CREATE TYPE project as OBJECT
(
PROJECT_ID INTEGER,
PROJECT_ASSIGNED_MEMBER REF MEMEBER,
PROJECT_TITLE VARCHAR2(30)
);
I had to create an object table of type project and alter it
CREATE TABLE PROJECT_TABLE OF PROJECT;
ALTER TABLE PROJECT_TABLE ADD PRIMARY KEY(PROJECT_ID);
ALTER TABLE PROJECT_TABLE ADD (CONSTRAINT NULL_CHK CHECK(PROJECT_TITLE IS NOT NULL);
No this is where I start to have trouble, I have been shown how to insert values to a table when all the values are of type ref, but when I include the other types I'm unsure of the syntax.
This was my attempt:
INSERT INTO PROJECT_TABLE
SELECT 1, REF(M)
FROM MEMEBER M
WHERE M.MEMBER_ID =1, 'KING KONG';
Could someone shed some light on the syntax for me please?

After some more research I found the solution:
INSERT INTO PROJECT_TABLE
(PROJECT_ID,
PROJECT_ASSIGNED_MEMBER,
PROJECT_TITLE)VALUES(
2,
(SELECT REF(M) FROM project_resources M WHERE M.member_id = 2),
'Bomb');

Related

Get data from nested tables

I'm starting with object-oriented databases and I have a lot of questions about it :-(
Having the following structure:
CREATE OR REPLACE TYPE typeAuthor AS OBJECT(
aId INTEGER,
aName VARCHAR(60),
aSurname VARCHAR(200),
);
CREATE TABLE tableAuthors OF typeAuthor (aId PRIMARY KEY)
NESTED TABLE aArticles STORE AS aArticles_nt;
CREATE OR REPLACE TYPE typeListAuthors AS TABLE OF REF typeAuthor;
CREATE OR REPLACE TYPE typeUniversity AS OBJECT(
uniId INTEGER,
uAlias VARCHAR(16),
uName VARCHAR(20),
uLocation VARCHAR(150),
uAuthors typeListAuthors
);
CREATE TABLE tableUniversity OF typeUniversity (uniId PRIMARY KEY)
NESTED TABLE uAuthors STORE AS uAuthors_nt;
If I do a SELECT, for example:
SELECT u.uAuthors from tableUniversity u WHERE u.uniId = 1;
It returns all the data of the objects stored in the table that matches with the condition, but... How can I get only the names of the Authors?
I tried with
SELECT u.uAuthors.aName from tableUniversity u WHERE u.uniId = 1;
But it doesn't work.
Probably this is a basic question, but as I said, I'm starting with this and is being a little bit confusing to me.
You can unnest the inner collection with:
from tableUniversity u
cross join table (u.uAuthors) a
and dereference the value returned from that, which you can access as column_value:
SELECT deref(a.column_value)
from tableUniversity u
cross join table (u.uAuthors) a
and then you can access the aName field from each dereferenced object:
SELECT deref(a.column_value).aname
from tableUniversity u
cross join table (u.uAuthors) a
WHERE u.uniId = 1;
db<>fiddle

SCOPE for a table of REFs

I am designing an object-relational model with Oracle (18.4.0) and I would like to add a SCOPE constraint to a table type column of an object table. Is it possible? Here a simplified model:
CREATE OR REPLACE TYPE t_cycler AS OBJECT (
name VARCHAR2(50)
);
CREATE TABLE cycler OF t_cycler (
name PRIMARY KEY
);
CREATE OR REPLACE TYPE t_cycler_list IS TABLE OF REF t_cycler;
CREATE OR REPLACE TYPE t_team AS OBJECT (
name VARCHAR2(50),
cyclers t_cycler_list
);
CREATE TABLE team OF t_team (
name PRIMARY KEY
)
NESTED TABLE cyclers STORE AS cyclers_tab;
I need that team.cyclers only contains REFs to objects in cycler. I look into the documentation but unfortunately it does not say a lot about SCOPE constraint, like here:
You can constrain a column type, collection element, or object type
attribute to reference a specified object table. Use the SQL
constraint subclause SCOPE IS when you declare the REF.
But the only example it provides is about a simple column type. I tried specifying SCOPE IS cycler in several ways inside the creation of the team table but with no results.
You want to add the scope to the COLUMN_VALUE pseudo-column of the nested table:
ALTER TABLE cyclers_tab ADD SCOPE FOR ( COLUMN_VALUE ) IS cycler;
If you then do:
INSERT INTO cycler ( name ) VALUES ( 'c1.1' );
INSERT INTO cycler ( name ) VALUES ( 'c1.2' );
INSERT INTO team (
name,
cyclers
) VALUES (
'team1',
t_cycler_list(
( SELECT REF(c) FROM cycler c WHERE name = 'c1.1' ),
( SELECT REF(c) FROM cycler c WHERE name = 'c1.2' )
)
);
Then you can insert the row. But, if you have another table of the same object type:
CREATE TABLE cycler2 OF t_cycler (
name PRIMARY KEY
);
INSERT INTO cycler2 ( name ) VALUES ( 'c2.1' );
And try to do:
INSERT INTO team (
name,
cyclers
) VALUES (
'team2',
t_cycler_list(
( SELECT REF(c) FROM cycler2 c WHERE name = 'c2.1' )
)
);
Then you get the error:
ORA-22889: REF value does not point to scoped table
db<>fiddle here

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.

ORA-00936: missing expression error when inserting values

I spend lot of time searching where i made the mistake but i was unable to find it when its going to insert the last record there is a error message showing "ORA-00936: missing expression" How to solve this please help me
create type pearson_types as object(
name varchar2(50),
sysID char(6)
)NOT FINAL;
create type doctor_types under pearson_types(
regNo char(10),
specialization varchar2(25)
)
create table doctor of doctor_types(
regNo primary key
)
create type hospVisits_types as object(
hosChg float,
vDate varchar2(20),
refDoc REF doctor_types,
docChg float
)
create type hospvisits_tbl_types as table of hospVisits_types
create type phone_arr as VARRAY(3) of char(10)
create type patient_types under pearson_types
(
id char(10),
dob varchar(20),
phone phone_arr,
hospVisits hospvisits_tbl_types
)
create table patients of patient_types(
id primary key
)nested table hospVisits store as Hospital_tables
alter table Hospital_tables add scope for (refDoc) is doctor
insert into doctor values ('Dr.k.perera','D001','1223441234','Gynecologist');
insert into doctor values ('Dr.p.weerasingha','D002','1234421131','Dermatalogist');
insert into doctor values ('Prof .S. Fernando','D003','2342111322','Pediatrician');
insert into doctor values ('Dr.k.Sathgunanathan','D004','2344114344','Pediatrician');
insert into patients values('Sampath Weerasingha','P001','732821122V','23-JAN-73',phone_arr('0332124222'),hospvisits_tbl_types(hospVisits_types(50.00,'24-MAY-06',select ref (a) from doctor a where a.regNo='1223441234',500.00)))
Add parentheses to SELECT statements inside a SQL statement:
insert into patients values(
'Sampath Weerasingha','P001','732821122V','23-JAN-73',phone_arr('0332124222'),
hospvisits_tbl_types(hospVisits_types(50.00,'24-MAY-06',
( -- ADD ME
select ref (a) from doctor a where a.regNo='1223441234'
) -- ADD ME
,500.00))
);

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).