Let object id within second table be unique - oracle

I got the following sql:
create or replace type MEDIUM_TYPE AS OBJECT
(
me_movie REF MOVIE_TYPE,
me_rating varchar2(2),
me_runtime number(3,0),
me_release_year number(4,0),
me_list_price number(3,2),
me_our_price number(3,2),
me_availability varchar2(128),
me_aspect_ratio varchar2(8),
me_encoding number (1,0),
me_subtitle_language SUBTITLE_LANGUAGE_TYPE,
me_number_of_discs number (1,0)
)not final
/
create table DVD of MEDIUM_TYPE
object id system generated
/
How can i make sure that me_movie in the dvd table is unique?
And also, how can i do something like this?
mo_release_year number(4,0) BETWEEN 1900 AND 2100,

It's pretty much the same syntax as for relational tables:
create table DVD of MEDIUM_TYPE
( me_movie primary key )
object id system generated
/
The one problem you have is that you will run into this error:
ORA-02329: column of datatype REF cannot be unique or a primary key
Which admittedly is a bit of a showstopper. You will need to re-think your whole model. Sorry about that.

Related

Oracle Object Type and Object Table

I have created an object type and a table. I would like to know how select, insert, update and delete operation on it.
create table employee_info (
empid number,
emp_name varchar2(50),
department varchar2(20),
designation varchar2(50),
salary number
);
create type employee_info_obj is object (
empid number,
department varchar2(50),
designation varchar2(50),
salary number
);
create type employee_info_obj_t is
table of employee_info_obj ;
You have only created an object type and an unrelated database table. If you want a database table based on the type, you need to create one:
create table employee_info of employee_info_obj;
While it can be nice in certain programming scenarios to have a type synced to a table, there are some downsides such as it being harder to add columns later, and third party tool support since the object table will not be listed in user_tables but only in user_object_tables and user_all_tables, so I would question the usefulness of this approach.
dbFiddle

ORA-00909 error when Insert object in object table

I am getting an error ORA-00909 in when inserting an object of a superType in an object table. These are the definitions for the objects:
CREATE OR REPLACE TYPE address AS OBJECT (
street VARCHAR(20),
country VARCHAR(20),
province VARCHAR(20),
city VARCHAR2(20),
zipcode VARCHAR(10)
) FINAL;
CREATE OR REPLACE TYPE company AS OBJECT (
CIF VARCHAR2(9),
code VARCHAR2(10),
name VARCHAR2(20),
signUpDate DATE,
email VARCHAR2(20),
adminAddress address
) NOT FINAL;
CREATE OR REPLACE TYPE inCourseCompany UNDER company (
postalAddress address,
numEmployees NUMBER
) FINAL;
And the object table:
CREATE TABLE companies_objtab OF company (PRIMARY KEY CIF) OBJECT IDENTIFIER IS PRIMARY KEY;
I try to insert an object with the following statement:
INSERT INTO companies_objtab VALUES (
company('J12345678','000001','Test Company',TO_DATE(sysdate, 'dd/mm/yyyy hh24:mi:ss'),'',address('','','','',''))
);
and I get error Error
SQL: ORA-00909: invalid number of arguments
00909. 00000 - "invalid number of arguments"
However, when I insert an object of the subtype inCourseCompany it is inserted correctly:
INSERT INTO companies_objtab VALUES (
inCourseCompany('G11111111','','',TO_DATE(sysdate, 'dd/mm/yyyy hh24:mi:ss'),'',address('','','','',''), address('','','','',''), 100)
);
Any hint about what causes the error?
I am using Oracle SQL Developer 4.0.2.15.21 and Oracle Database Express Edition 11g Release 2.
Thank you in advance.
i tried all your statements right as you posted them (copy-paste). Both on 12c and 11gR2. Everything worked, both inserts. The only thing I noticed is that your create table is a bit incorrect. This is the correct one (but this does not explain the error you get). HTH KR
CREATE TABLE companies_objtab OF company (CIF PRIMARY KEY) OBJECT IDENTIFIER IS PRIMARY KEY;
Maybe try dropping the table and creating it again.

00904 When Creating Table

Here is the code I'm using in Oracle SQL Developer :
CREATE TABLE ORDER_ITEMS(
ITEM_NO NUMBER(10),
ITEM_DESCRIPTION VARCHAR(50),
SIZE VARCHAR(5),
COST NUMBER(8,2),
QUANTITY NUMBER(10),
TOTAL NUMBER(8,2),
ITEM_ORDER_NO NUMBER(10),
CONSTRAINT ITM_NO_PK PRIMARY KEY (ITEM_NO));
The error has to do with the SIZE and COST tables, if I change the names on those two tables (for example put an A at the end of them (SIZEA COSTA)) then the code works. Why are these table names invalid ?
I think you mean column where you're writing table. Also SIZE is a reserved word in Oracle SQL, as is NUMBER.
https://docs.oracle.com/cd/B19306_01/server.102/b14200/ap_keywd.htm

Adding constraint to supertable with child instances in an Oracle DB

I've got a hierarchy pretty similar to this one in an Oracle Database
CREATE TYPE PersonUdt AS OBJECT(
personId number(10),
Name varchar(20)
)INSTANTIABLE NOT FINAL;
CREATE OR REPLACE TYPE PatientUdt under PersonUdt(
insurancePlan varchar(100)
);
CREATE OR REPLACE TYPE DoctorUdt under PersonUdt(
area varchar(20)
);
CREATE TABLE Person of PersonUdt(
personId PRIMARY KEY
)OBJECT IDENTIFIER IS SYSTEM GENERATED;
I've got some insertions on the table,like
INSERT INTO person VALUES(DoctorUdt(1, 'Alfred', 'Area One'));
I would like to create a constraint to limit the area in which the a doctor can work. Let's say, limit it to Area one, two and three.
Is it possible to do this using ALTER TABLE x ADD CONSTRAINT... functions?
Thanks in advance!

Contraint to set one column as the sum of two others automatically

I'm wondering is it possible to use a constraint to set the value of one column to be sum of two others. For example given the following tables:
CREATE TABLE Room (
Room_Num NUMBER(3),
Room_Band_ID NUMBER(2),
Room_Type_ID NUMBER(2),
Room_Price NUMBER(4),
PRIMARY KEY (Room_Num),
FOREIGN KEY(Room_Band_ID)
REFERENCES Room_Band(Room_Band_ID),
FOREIGN KEY(Room_Type_ID)
REFERENCES Room_Type(Room_Type_ID)
);
CREATE TABLE Booking (
Booking_ID NUMBER(10) NOT NULL,
GuestID NUMBER(4) NOT NULL,
StaffID NUMBER(2) NOT NULL,
Payment_ID NUMBER(4) NOT NULL,
Room_Num NUMBER(3) NOT NULL,
CheckInDate DATE NOT NULL,
CheckOutDate DATE NOT NULL,
Booking NUMBER(2) NOT NULL,
Price NUMBER(4),
PRIMARY KEY (Booking_ID),
FOREIGN KEY(GuestID)
REFERENCES Guest(GuestID),
FOREIGN KEY(StaffID)
REFERENCES Staff(StaffID),
FOREIGN KEY(Payment_ID)
REFERENCES Payment(Payment_ID),
FOREIGN KEY(Room_Num)
REFERENCES Room(Room_Num)
);
I know it is possible to do something like:
Constraint PriceIs CHECK (Booking.Price=(Room.Room_Price*
(Booking.CheckOutDate - Booking.CheckInDate)));
Is it also possible to set up a constraint that doesn't just ensure that the price is correct, but to calculate the price automatically into the price field for the relevant tuple?
Update,
So I've tried to set up a trigger as follows:
CREATE OR REPLACE trigger PriceCompute
AFTER INSERT ON Booking
FOR each row
BEGIN
UPDATE Booking
SET
SELECT (Room.Room_Price*(Booking.CheckOutDate - Booking.CheckInDate))
INTO
Booking.Price
FROM Booking
JOIN ROOM ON Booking.Room_Num = Room.Room_Num
END;
/
But I'm getting the following errors back:
Can anyone see where I'm going astray here, as its beyond me.
Yes, you can. Here are your options. Listed in order of my personal preference:
You can have a table without this column. And create a view that will be calculating this column on a fly.
You may use oracle virtual columns
create table Room (
...
price NUMBER GENERATED ALWAYS AS (room_price*(checkOut-checkIn)) VIRTUAL,
...)
You may use actual column (same as 2, per Dave Costa):
create table Room (
...
price AS (room_price*(checkOut-checkIn)),
...)
You can write trigger to populate it (like Mat M suggested)
You can write stored procedure, but it will be an overkill in this situation
I think you would have to put a trigger on both tables for whenever the price value of the room is changed or the checkout/in dates are changed, it will update the PriceIs field from your calculation.
If you don't need the calculated portion stored in an actual field, you can always create a view that calculates it whenever you look at the view.
I think the better solution is to use a view that calculates the value on the fly. But regarding your attempt to create a trigger, you should use :new.<column_name> to refer to the values being inserted into the Booking table. You don't need to perform updates and queries on that table to get or modify the values in the row that is being inserted*. You just refer to them as variables. So you would want to do something like:
SELECT (Room.Room_Price*(:new.CheckOutDate - :new.CheckInDate))
INTO
:new.Price
FROM ROOM WHERE :new.Room_Num = Room.Room_Num
*In fact, you can't perform queries or updates on the table whose modification invoked the trigger in the first place. You would get the infamous "mutating table" error if your trigger actually compiled and ran.

Resources