on sql Foreign key - database

Can someone help me in SQL I'm using Oracle SQL*plus
Create the following tables.
Table Student:
stdNo CHAR(5) This is the Primary Key
lastname VARCHAR(25) Must be Not Null
givennames VARCHAR(50) Must be Not Null
Dept CHAR(4)
Table Course:
courseID CHAR(8) This is the Primary Key
courseTitle VARCHAR(50) Must be Unique and Not Null
Cost DECIMAL(6,2) Ensure Cost is greater or equal to zero
Credits INT Ensure that Credits are between 0 and 200. Also the default value is 2
Table Semester:
semesterID CHAR(5) This is the Primary Key
semesterCode INT Ensure that semesterCode is Between 1 and 4
Year INT Ensure that year is Between 2000 and 9999
Table Register:
stdNo CHAR(5) Foreign Key referenced to stdNo in Student table, On update cascade On delete cascade
courseID CHAR(8) Foreign Key referenced to courseID in Course table, On update cascade On delete cascade
semesterID CHAR(5) Foreign Key referenced to semesterID in Semester table, On update cascade On delete cascade
Grade CHAR(2)
Mark DECIMAL(4,2) Mark should be between 0.00 and 100.00
Primary Key (stdNo, courseID, semesterID)
Here in SQL (I'm using Oracle SQL*plus) .. table STD , SEMESTER works with me, but table COURSE I did not know how to put default value is 2 and table REGISTER dose not work with me at all :(
CREATE TABLE STD
(
STDNO CHAR(5) PRIMARY KEY,
LASTNAME VARCHAR(25) NOT NULL,
GIVENNAME VARCHAR(50) NOT NULL,
DEPT CHAR(4)
);
CREATE TABLE SEMESTER
(
SEMESTERID CHAR(5) PRIMARY KEY,
SEMESTERCODE INT CHECK(SEMESTERCODE BETWEEN 1 AND 4),
YEARS INT CHECK(YEARS BETWEEN 2000 AND 9999)
);
CREATE TABLE COURSE
(
COURSEID CHAR(8) PRIMARY KEY,
COURSETITLE VARCHAR(50) NOT NULL UNIQUE,
COST DECIMAL(6,2) CHECK(COST >= 0),
CREDITS INT CHECK(CREDITS BETWEEN 0 AND 200)
);
CREATE TABLE REGISTER
(
STDNO CHAR(5)
FOREIGN KEY REFERENCES STD(STDNO)
ON UPDATE CASCADE ON DELETE CASCADE,
COURSEID CHAR(5)
FOREIGN KEY REFERENCES COURSE(COURSEID)
ON UPDATE CASCADE ON DELETE CASCADE,
SEMESTERID CHAR(5)
FOREIGN KEY REFERENCES SEMESTER(SEMESTERID)
ON UPDATE CASCADE ON DELETE CASCADE,
GRADE CHAR(2),
MARK DECIMAL(4,2) CHECK(MARK BETWEEN 0.00 AND 100.0),
PRIMARYKEY(STDNO,COURSEID,SEMESTERID)
);

Please find below the solution.
COURSE - please use the below script to have a default value for CREDITS column
CREATE TABLE COURSE
(
COURSEID CHAR(8) PRIMARY KEY,
COURSETITLE VARCHAR(50) NOT NULL UNIQUE,
COST DECIMAL(6,2) CHECK(COST >= 0),
CREDITS INT DEFAULT 2 CHECK(CREDITS BETWEEN 0 AND 200)
);
REGISTER - Oracle Does not allow a Foreign Key Constraint with "ON UPDATE CASCADE". So you will have to use triggers for the same. Find below the scripts that you could make use of,
CREATE TABLE REGISTER
(
STDNO CHAR(5),
COURSEID CHAR(8), -- UPDATED THE DATATYPE TO SAME AS MASTER TABLE
SEMESTERID CHAR(5),
GRADE CHAR(2),
MARK DECIMAL(4,2) CHECK(MARK BETWEEN 0.00 AND 100.0),
CONSTRAINT register_pk PRIMARY KEY(STDNO,COURSEID,SEMESTERID),
CONSTRAINT register_fk1 FOREIGN KEY (STDNO) REFERENCES STD(STDNO)
ON DELETE CASCADE,
CONSTRAINT register_fk2 FOREIGN KEY (COURSEID) REFERENCES COURSE(COURSEID)
ON DELETE CASCADE,
CONSTRAINT register_fk3 FOREIGN KEY (SEMESTERID) REFERENCES SEMESTER(SEMESTERID)
ON DELETE CASCADE
);
CREATE OR REPLACE TRIGGER cascade_stdno_update
AFTER UPDATE OF stdno ON std
FOR EACH ROW
BEGIN
UPDATE REGISTER
SET stdno = :NEW.stdno
WHERE stdno = :OLD.stdno;
END;
/
CREATE OR REPLACE TRIGGER cascade_courseid_update
AFTER UPDATE OF courseid ON course
FOR EACH ROW
BEGIN
UPDATE REGISTER
SET courseid = :NEW.courseid
WHERE courseid = :OLD.courseid;
END;
/
CREATE OR REPLACE TRIGGER cascade_semesterid_update
AFTER UPDATE OF semesterid ON semester
FOR EACH ROW
BEGIN
UPDATE REGISTER
SET semesterid = :NEW.semesterid
WHERE semesterid = :OLD.semesterid;
END;
/

Related

How can I reference 2 different columns in 2 different tables simultaneously

This is an assignment and I have been given this diagram for reference - https://imgur.com/gallery/wRkArmQ
There are other tables that I will include but the issue seems to be with the tables section and time_slot. In the diagram, they reference each other but I don't know how to. Any comments are helpful! I am using Oracle btw, here is the code -
create table department (
dept_name varchar(15) primary key,
building varchar(10),
budget int
);
create table instructor (
id varchar(10) primary key,
name varchar(15) not null,
dept_name varchar(20) not null
references department(dept_name) on delete cascade,
salary int not null
);
create table course (
course_id varchar(10) primary key,
title varchar(10),
dept_name varchar(15)
references department(dept_name) on delete cascade,
credits int
);
create table classroom (
building varchar(10) not null,
room_no varchar(5) not null,
capacity int not null,
primary key (building, room_no)
);
create table section (
course_id varchar(10) not null
references course(course_id),
sec_id varchar(10) not null,
semester varchar(10) not null,
year varchar(10) not null,
building varchar(10) not null
references classroom(building),
room_no varchar(5) not null
references classroom(room_no),
time_slot_id varchar(5) not null
references time_slot(time_slot_id),
primary key (course_id, sec_id, semester, year)
);
create table time_slot (
time_slot_id varchar(5) not null
references section(time_slot_id),
day varchar(10) not null,
start_time date not null,
end_time date not null,
primary key (time_slot_id, day, start_time)
);
create table teaches (
id varchar(10) primary key
references instructor(id) on delete cascade,
course_id varchar(15) not null
references section(course_id),
sec_id varchar(5) not null
references section(sec_id),
semester varchar(15)
references section(semester),
year int not null
references section(year)
);
create table student (
id varchar(10) not null primary key,
name varchar(20) not null,
dept_name varchar(15) not null
references department(dept_name) on delete cascade,
tot_cred int not null
);
create table advisor (
s_id varchar(10) primary key
references student(id) on delete cascade,
i_id varchar(6)
references instructor(id) on delete cascade
);
create table prereq (
course_id varchar(10)
references course(course_id) on delete cascade,
prereq_id varchar(10)
references course(course_id) on delete cascade,
primary key (course_id, prereq_id)
);
create table takes (
id varchar(10) not null
references student(id) on delete cascade,
course_id varchar(10) not null
references section(course_id) on delete cascade,
sec_id varchar(10) not null
references section(sec_id) on delete cascade,
semester varchar(10) not null
references section(semester) on delete cascade,
year int not null
references section(year) on delete cascade,
grade varchar(10) not null,
primary key (id, course_id, sec_id, semester, year, grade)
);
This is the output -
Table created.
Table created.
Table created.
Table created.
ORA-02270: no matching unique or primary key for this column-list
ORA-00942: table or view does not exist
ORA-00942: table or view does not exist

Creting FOREIGN KEY constraint on multiple columns with one of them being constant value

When I have table with PRIMARY KEY from 2 columns:
CREATE TABLE SizeTypes
(
TypeID tinyint NOT NULL,
SizeID tinyint NOT NULL,
Name varchar(100) NOT NULL,
CONSTRAINT PK_SizeType
PRIMARY KEY (TypeID, SizeID)
)
How can I create second table with a foreign key that have 1st constant value and 2nd from column like below:
CREATE TABLE Something
(
ID INT IDENTITY(1,1) PRIMARY KEY,
SizeTypeID_1 TINYINT,
SizeTypeID_2 TINYINT,
SizeTypeID_3 TINYINT,
CONSTRAINT FK_Something_SizeTypes_1
FOREIGN KEY (1, SizeTypeID_1)
REFERENCES SizeTypes(TypeID, SizeID),
CONSTRAINT FK_Something_SizeTypes_2
FOREIGN KEY (2, SizeTypeID_2)
REFERENCES SizeTypes(TypeID, SizeID),
CONSTRAINT FK_Something_SizeTypes_3
FOREIGN KEY (3, SizeTypeID_3)
REFERENCES SizeTypes(TypeID, SizeID)
)
This can be done using FOREIGN KEY, if yes then how?
If no then what other ways to do this I have? Triggers on INSERT and UPDATE for table something and on DELETE for table SizeTypes? Any other choices I have?
It looks like the following code will let you create suitable check constraints with the check implemented by a separate function:
-- Create the first table.
create table SizeTypes(
TypeId TinyInt not NULL,
SizeId TinyInt not NULL,
Name VarChar(100) not NULL,
constraint PK_SizeType primary key ( TypeId, SizeId ) );
go
-- Create a function to implement the logic for the check constraint.
create function CheckSizeTypeId(
#TypeId TinyInt, #SizeId TinyInt )
returns Int
as begin
-- Replace the following statement with the logic for your check.
if #SizeId >= 0 and #SizeId <= ( select SizeId from SizeTypes where TypeID = #TypeID )
return 1;
return 0;
end;
go
-- Create the second table with the check constraints.
create table Something(
Id Int identity(1,1) primary key,
SizeTypeId_1 TinyInt,
SizeTypeId_2 TinyInt,
SizeTypeId_3 TinyInt,
constraint Check_SizeTypeId_1 check ( dbo.CheckSizeTypeId( 1, SizeTypeId_1 ) = 1 ),
constraint Check_SizeTypeId_2 check ( dbo.CheckSizeTypeId( 2, SizeTypeId_2 ) = 1 ),
constraint Check_SizeTypeId_3 check ( dbo.CheckSizeTypeId( 3, SizeTypeId_3 ) = 1 ) );
go
-- Houseclean.
drop table SizeTypes;
drop table Something;
drop function CheckSizeTypeId;
Note that the constraints restrict what you can do with values in Something. Changes in SizeTypes will not revalidate data in Something, though that could be implemented in a trigger on SizeTypes.

Oracle create table Invalid Name / Constraint

I met an error in an SQL command when trying to create a table in SQL. Below is my command:
CREATE TABLE Registration
(
registrationID varchar2(5) NOT NULL CONSTRAINT registrationID PRIMARY KEY,
competitionID varchar2(5) NOT NULL CONSTRAINT competitionID REFERENCES Competition(competitionID),
competitorID varchar2(5) NOT NULL CONSTRAINT competitorID REFERENCES Competitor(competitorID),
categoryType varchar2(6) NOT NULL,
entryFeeStatus char(1) NOT NULL,
creditCardNumber number(16),
datePaid date
);
My competitionID is primary key of Competition table.
My competitorID is primary key of Competitor table.
The error shown is:
Error report -
SQL Error: ORA-02264: name already used by an existing constraint
02264. 00000 - "name already used by an existing constraint"
*Cause: The specified constraint name has to be unique.
*Action: Specify a unique constraint name for the constraint.
May I know what I should change in my statement? Thank you.
Below are the Competition and Competitor tables that I created:
CREATE TABLE Competition
(
competitionID varchar2(5) NOT NULL CONSTRAINT competitionID PRIMARY KEY,
timePlanned date NOT NULL,
country varchar2(50) NOT NULL,
city varchar2(50),
address varchar2(50),
entryFee number(4) NOT NULL
);
CREATE TABLE Competitor
(
competitorID varchar2(5) NOT NULL CONSTRAINT competitorID PRIMARY KEY,
firstName varchar2(9) NOT NULL,
lastName varchar2(9) NOT NULL,
dateOfBirth date NOT NULL,
nationality varchar2(12),
gender varchar2(1) NOT NULL,
lifetimeRanking number(6),
totalPrizeMoney number(6)
);
You mixed up the two different ways to specify foreign keys. And had an extra comma.
CREATE TABLE Registration
(
registrationID varchar2(5) NOT NULL CONSTRAINT registrationID PRIMARY KEY,
competitionID varchar2(5) NOT NULL CONSTRAINT competitionIDfk REFERENCES Competition(competitionID),
competitorID varchar2(5) NOT NULL CONSTRAINT competitorIDfk REFERENCES Competitor(competitorID)
)
Foreign keys can either be specified per column:
columnname datatype CONSTRAINT constraintname REFERENCES tablename [ (column) ]
Or per table:
CONSTRAINT constraintname FOREIGN KEY (column-list) REFERENCES tablename [ (column-list) ]
BOOLEAN is not valid SQL type. Use NUMBER(1) with 0 and 1, CHAR(1) or VARCHAR2(1) with 'Y' and 'N' values or other surrogate representation.

How to check a value from a nother table

I have Table:
create table Authorized(
diver_number int not null,
level_name char(30) not null,
constraint PK_Authorized primary key (diver_number, level_name),
Constraint FK_diver_number1 foreign key (diver_number) references Diver(diver_number)
on update cascade on delete cascade,
Constraint FK_level_name foreign key (level_name) references Level(name)on update
cascade on delete cascade,
club_number int Constraint FK_club_number foreign key (club_number) references DivingClub(number)
on update cascade on delete cascade not null,
authorization_date date not null,
picture image)
And atable:
create table Works_for(
diver_number int not null,
club_number int not null,
constraint PK_Works_for primary key (diver_number, club_number),
Constraint FK_diver_number2 foreign key (diver_number) references Diver(diver_number)
on update cascade on delete cascade ,
Constraint FK_club_number2 foreign key (club_number) references DivingClub (number)on update
cascade on delete cascade,
start_working_date date not null,
end_working_date date)
When i add diver_number to table Works_for, i want to check if this diver is a "Guide" (level_name in Authorized table). How can i check it?
I would think your scalar function would be more like this.
CREATE FUNCTION dbo.checkADate(#diver_number int) RETURNS BIT AS
BEGIN
declare #Found bit
select #Found = count(*)
from Authorized
WHERE diver_number = #diver_number
and level_name = 'Guide'
return #Found
END

Insert primary key identity(id) into other table as foreign key

I have two tables in SQL(InjuryScenario and ProductTypeDet)
CREATE TABLE InjuryScenario
(
InjuryScenario_id int identity(1,1),
InjuryScenario_name varchar(80),
InjuryDay int,
InjuryMonth int,
InjuryYear int,
InjuryDesc varchar(80),
InjuryComments varchar(50),
AlmostInjury int,
InjuryInSchool varchar(20),
ProductInjury varchar(20),
Cause_id int,
CauseType_id int,
CauseChar_id int,
Place_id int,
PlaceType_id int,
Username varchar(50),
InjuryDate_id int,
constraint pk_InjuryScenario_id primary key (InjuryScenario_id),
constraint fk_Cause_InjuryScenario foreign key(Cause_id) references Cause(Cause_id) on delete cascade,
constraint fk_CauseType_InjuryScenario foreign key(CauseType_id) references CauseType(CauseType_id) on delete no action,
constraint fk_Place_InjuryScenario foreign key(Place_id) references Place(Place_id) on delete cascade,
constraint fk_PlaceType_InjuryScenario foreign key(PlaceType_id) references PlaceType(PlaceType_id) on delete no action,
constraint fk_Users_InjuryScenario foreign key(Username) references Users(Username) on delete cascade,
constraint fk_InjuryDate_InjuryScenario foreign key(InjuryDate_id) references InjuryDate(InjuryDate_id) on delete cascade,
)
CREATE TABLE ProductTypeDet
(
ProductCategory_id int,
ProductType_id int,
Product_name varchar(80),
Brand_name varchar(80),
Notes varchar(80),
Manufacturer_name varchar(80),
Launch_Date date,
ProdTypeDesc varchar(80),
ProductInjury varchar(20),
Status_id int,
SafetyAct_id int,
InjuryScenario_id int foreign key references InjuryScenario(InjuryScenario_id),
constraint fk_ProductCategory_ProductTypeDet foreign key(ProductCategory_id) references ProductCategory(ProductCategory_id) on delete cascade,
constraint fk_ProductType_ProductTypeDet foreign key(ProductType_id) references ProductType(ProductType_id) on delete no action,
constraint fk_ProductStatus_ProductTypeDet foreign key(Status_id) references ProductStatus(Status_id) on delete cascade,
constraint fk_SafetyAct_ProductTypeDet foreign key(SafetyAct_id) references Product(SafetyAct_id) on delete no action
)
in VS i have Insert function that inserts data from the user to the tables.
i built SQL trigger-
CREATE TRIGGER tr_InjuryScenario_ForInsert
ON InjuryScenario
FOR INSERT
AS
BEGIN
DECLARE #Id int
SELECT #Id = InjuryScenario_id from inserted
INSERT INTO ProductTypeDet(InjuryScenario_id)
values(#Id)
END
i have a problem that in ProductTypeDet table two rows created- one from the trigger(just with the InjuryScenario_id and the other coloumns are null) and the other one from the Insert function in vs(coloumns filled from the user selections and the InjuryScenario_id is null).
how can i linked those 2 rows into one?
You never write a trigger like that! Inserted and deleted tables may contain multiple row and you tried to set the value to a scalar variable. (incidentally you should unit test triggers with multiple record inserts/updates or deletes) Use a set based propcess.
INSERT INTO ProductTypeDet(InjuryScenario_id)
SELECT InjuryScenario_id from inserted

Resources