Oracle creating Table using super class attribute as primary key - sql

I have a sales_person_type defined as follows:
CREATE OR REPLACE TYPE sales_person_type UNDER person_type (
salesAppointments sales_person_appointments
);
this is a subclass of the person_type defined as such:
CREATE OR REPLACE TYPE person_type AS OBJECT (
personID NUMBER,
forename VARCHAR2(30),
surname VARCHAR2(20),
dateOfBirth DATE
) NOT FINAL;
I'm trying to create a table of sales persons and specifying the primary key as the super class attribute like this:
CREATE TABLE sales_person_table OF sales_person_type (
PRIMARY KEY (personID),
OBJECT IDENTIFIER IS PRIMARY KEY)
NESTED TABLE salesAppointments STORE AS sale_appointment_table (
(PRIMARY KEY(NESTED_TABLE_ID, appointmentID))
ORGANIZATION INDEX COMPRESS)
RETURN AS LOCATOR
But I'm getting this error:
SQL Error: ORA-02330: datatype specification not allowed
02330. 00000 - "datatype specification not allowed"
*Cause: An attempt was made to specify the data type in the column
constraint specification of an object table.
I'm think it's because im trying to assign the primary key as the super class attibute? Is this the correct syntax for this?
Cheers.
EDIT:
Works now, thanks Dimitry.

Check the syntax of CREATE TABLE for OID clause:
SQL> CREATE OR REPLACE TYPE person_type AS OBJECT (
2 personID NUMBER,
3 forename VARCHAR2(30),
4 surname VARCHAR2(20),
5 dateOfBirth DATE
6 ) NOT FINAL;
7 /
SQL> create or replace type sale_appointment is object
2 (
3 appointmentID integer
4 );
5 /
Тип создан.
SQL> create type sales_person_appointments as table of sale_appointment;
2 /
SQL> CREATE OR REPLACE TYPE sales_person_type UNDER person_type (
2 salesAppointments sales_person_appointments
3 );
4 /
SQL> CREATE TABLE sales_person_table OF sales_person_type (
2 PRIMARY KEY (personID)
3 )
4 OBJECT IDENTIFIER IS PRIMARY KEY
5 NESTED TABLE salesAppointments STORE AS sale_appointment_table (
6 (PRIMARY KEY(NESTED_TABLE_ID, appointmentID))
7 ORGANIZATION INDEX COMPRESS)
8 RETURN AS LOCATOR
9 /
Table created.

Related

Getting an error of invalid identifier when try to create relationship between two tables in Oracle SQL developer? [duplicate]

This question already has an answer here:
A CREATE statement with quoted fields in Oracle
(1 answer)
Closed 1 year ago.
This is my device table
CREATE TABLE "DEVICE" (
"IMEI_Number" varchar(15),
"Device_Model" varchar(30),
"Device_Description" varchar(500),
"Assigned_Sim_Number" varchar(11),
"Activation_Date" timestamp,
"Deactivation_Date" timestamp,
"Manufacturer_ID" int,
"Customer_ID" int,
PRIMARY KEY ("IMEI_Number")
);
Then I have the manufacturer table which is
CREATE TABLE "MANUFACTURER" (
"Manufacturer_ID" int,
"Manufacturer_Name" varchar(30),
PRIMARY KEY ("Manufacturer_ID")
);
and I trying to create a relationship between these and getting the ORA-00904: "MANUFACTURER_ID": invalid identifier
My relationship code is
ALTER TABLE DEVICE
ADD FOREIGN KEY (Manufacturer_ID) REFERENCES MANUFACTURER(Manufacturer_ID);
That's just awful. Don't use double quotes when creating objects in Oracle as you'll have to use them every time you reference those objects, and match letter case every time.
SQL> alter table device add constraint fk_mf foreign key ("Manufacturer_ID")
2 references manufacturer ("Manufacturer_ID");
Table altered.
SQL>
A better option would be
SQL> create table device (
2 imei_number varchar2(15),
3 device_model varchar2(30),
4 device_description varchar2(500),
5 assigned_sim_number varchar2(11),
6 activation_date timestamp,
7 deactivation_date timestamp,
8 manufacturer_id int,
9 customer_id int,
10 primary key (imei_number)
11 );
Table created.
SQL> create table manufacturer (
2 manufacturer_id int,
3 manufacturer_name varchar2(30),
4 primary key (manufacturer_id)
5 );
Table created.
SQL> alter table device add constraint fk_mf foreign key (manufacturer_id)
2 references manufacturer (manufacturer_id);
Table altered.
SQL>
(Note also VARCHAR2 datatype; use that instead of VARCHAR).
By default, Oracle stores names in uppercase into data dictionary, but you can reference them using any case you want (upper, lower, mixed). If you do use double quotes, then you have to use their names exactly as during creation phase.
The columns in the tables you've created are surrounded by double-quotes, making their names case-sensitive, while the alter statement does not use quotes, and thus can't match the case-sensitive column name.
The best practice would be to drop these quotes and make the column names case-insensitive. If this is not an option, you could use the same quotes in the alter statement too:
ALTER TABLE DEVICE
ADD FOREIGN KEY ("Manufacturer_ID") REFERENCES MANUFACTURER("Manufacturer_ID");
-- 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.

PL/SQL With Object Types PRIMARY KEY

I have create object relation type as below.
CREATE OR REPLACE TYPE familycar_t AS OBJECT (
make VARCHAR (10),
model VARCHAR(10),
year NUMBER (4),
fuel_type VARCHAR (10));
/
CREATE OR REPLACE TYPE sedan_t AS OBJECT (
familycar ref familycar_t,
cylinder_Size number(10));
/
CREATE TABLE familycar OF familycar_t (PRIMARY KEY (make,model));
Now I want to set primary for "Sedan" table as follow.
CREATE TABLE sedan OF sedan_t (PRIMARY KEY (familycar_t.make,familycar_t.model));
But Error occur like,
Error starting at line : 4 in command - CREATE TABLE sedan OF sedan_t
(PRIMARY KEY (familycar_t.make,familycar_t.model)) Error report - SQL
Error: ORA-00904: "FAMILYCAR_T"."MAKE": invalid identifier
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
What is the solution for it?
An alternative to using references is to use inheritance:
CREATE OR REPLACE TYPE familycar_t AS OBJECT (
make VARCHAR (10),
model VARCHAR(10),
year NUMBER (4),
fuel_type VARCHAR (10)
) NOT FINAL;
/
CREATE OR REPLACE TYPE sedan_t UNDER familycar_t (
cylinder_Size number(10)
);
/
CREATE TABLE familycar OF familycar_t (PRIMARY KEY (make,model));
CREATE TABLE sedan OF sedan_t (PRIMARY KEY (make,model));
However, you don't really need the sedan table in this case:
INSERT INTO familycar
SELECT sedan_t( 'Ford', 'Model-T', 1908, 'Petrol', 4 ) FROM DUAL UNION ALL
SELECT familycar_t( 'Ford', 'Model-A', 1903, 'Petrol' ) FROM DUAL;
SELECT f.*,
TREAT( VALUE(f) AS sedan_t ).cylinder_size AS cylinder_size
FROM familycar f;
Output:
MAKE MODEL YEAR FUEL_TYPE CYLINDER_SIZE
---------- ---------- ---------- ---------- -------------
Ford Model-T 1908 Petrol 4
Ford Model-A 1903 Petrol (null)
You cannot create an index on attributes whose type is REF (see here).
You can only define indexes on REF attributes or columns if the REF is scoped.
CREATE OR REPLACE TYPE sedan_t AS OBJECT (
familycar familycar_t,
cylinder_Size number(10)
);
/
CREATE TABLE sedan OF sedan_t (PRIMARY KEY (familycar.make, familycar.model));
Table SEDAN created.

ORA-00955 during SQL Table creation

I have been getting the error during a table creation. I know it means that the table name needs to change, but I don't see any object with the same name. A copy of the .lst is below.
Thanks
SQL> CREATE TABLE CUSTOMERtable
2 (
3 CUSTOMERID INT NOT NULL,
4 CUSTNAME VARCHAR2 (50) NOT NULL,
5 ADDRESS VARCHAR2 (100) NOT NULL,
6 PHONENUMBER VARCHAR2 (10) NOT NULL,
7 CONSTRAINT IDS_CUST_PK PRIMARY KEY (CUSTOMERID)
8 );
CREATE TABLE CUSTOMERtable
*
ERROR at line 1:
ORA-00955: name is already used by an existing object
SQL>
SQL>
SQL> CREATE TABLE RENTALStable
2 (
3 RENTALID INT NOT NULL,
4 OUTDATE DATE NOT NULL,
5 INDATE DATE NOT NULL,
6 LATEFEE INT,
7 DAMAGEFEE INT,
8 REWINDFEE INT,
9 ID_CUSTOMER INT,
10 CONSTRAINT RentalsTable_IDS_PK PRIMARY KEY (RENTALID),
11 FOREIGN KEY (ID_CUSTOMER) REFERENCES CUSTOMERtable(CUSTOMERID)
12 );
Table created.
This should find the object that's creating the problem:
select *
from user_objects
where object_name = 'CUSTOMERTABLE'
Notice that your statement, even if you write CUSTOMERtable ( upper and lower case), will try to create a table named CUSTOMERTABLE (upper case).
If you want to keep two objects with the same names but different case (and it seems not a good idea to me) you should use double quotes:
CREATE TABLE "CUSTOMERtable" ( ...

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