Demonstration of the
Relational Model
1. Create Tables with Constraints
Patient:
CREATE TABLE Patient (
Patient_ID SERIAL PRIMARY KEY,
First_Name VARCHAR(50),
Last_Name VARCHAR(50),
Gender VARCHAR(10) CHECK (Gender IN ('Male', 'Female', 'Other')),
Phone_No VARCHAR(15) UNIQUE NOT NULL,
Email VARCHAR(100) UNIQUE,
Date_of_Birth DATE,
Emergency_Contact VARCHAR(15),
Registration_Date DATE DEFAULT CURRENT_DATE,
Blood_Group VARCHAR(5),
Street VARCHAR(100),
City VARCHAR(50),
State VARCHAR(50)
);
Doctor:
CREATE TABLE Doctor (
Doctor_ID SERIAL PRIMARY KEY,
Name VARCHAR(100),
Gender VARCHAR(10),
Email VARCHAR(100) UNIQUE,
Phone_No VARCHAR(15) UNIQUE,
Joining_Date DATE,
Specialization VARCHAR(100),
Department_ID INT REFERENCES Department(Department_ID) ON DELETE SET NULL,
Consultation_Fee NUMERIC(8,2),
Availability BOOLEAN
);
Appointments:
CREATE TABLE Appointments (
Appointment_ID SERIAL PRIMARY KEY,
Patient_ID INT REFERENCES Patient(Patient_ID) ON DELETE CASCADE,
Doctor_ID INT REFERENCES Doctor(Doctor_ID) ON DELETE SET NULL,
Mode VARCHAR(20),
Consultation_Type VARCHAR(30),
Status VARCHAR(20),
Time_Slot VARCHAR(30),
Booking_Date DATE,
Appointment_Date DATE,
Reason TEXT
);
4.Billing:
CREATE TABLE Billing (
Appointment_ID INT REFERENCES Appointments(Appointment_ID) ON DELETE SET NULL,
Patient_ID INT REFERENCES Patient(Patient_ID) ON DELETE CASCADE,
Total_Amount NUMERIC(10,2),
Tax NUMERIC(6,2),
Discount NUMERIC(6,2),
Billing_Date DATE DEFAULT CURRENT_DATE,
Payment_Mode VARCHAR(50),
Payment_Status VARCHAR(20)
);
5.Medical Records:
CREATE TABLE Medical_Records (
Record_ID SERIAL PRIMARY KEY,
Patient_ID INT REFERENCES Patient(Patient_ID) ON DELETE CASCADE,
Blood_Pressure VARCHAR(20),
Weight_kg NUMERIC(5,2),
Height_cm NUMERIC(5,2),
Family_History TEXT,
Surgeries TEXT,
Allergies TEXT,
Past_Conditions TEXT,
Date_Updated DATE DEFAULT CURRENT_DATE
);
6.Prescription:
CREATE TABLE Prescription (
Prescription_ID SERIAL PRIMARY KEY,
Doctor_ID INT REFERENCES Doctor(Doctor_ID) ON DELETE SET NULL,
Patient_ID INT REFERENCES Patient(Patient_ID) ON DELETE CASCADE,
Diagnosis TEXT,
Medication TEXT,
Dosage TEXT,
Duration VARCHAR(50),
Follow_Up_Date DATE,
Date_Issued DATE DEFAULT CURRENT_DATE,
Notes TEXT
);
7.Department:
CREATE TABLE Department (
Department_ID SERIAL PRIMARY KEY,
Name VARCHAR(100),
Head_Doctor VARCHAR(100),
Contact_Email VARCHAR(100),
Phone VARCHAR(15),
Floor_No INT,
Room_Count INT,
Description TEXT,
Staff_Count INT,
Created_At DATE DEFAULT CURRENT_DATE
);
8.Staff:
CREATE TABLE Staff (
Staff_ID SERIAL PRIMARY KEY,
Name VARCHAR(100),
Role VARCHAR(50),
Department_ID INT REFERENCES Department(Department_ID) ON DELETE SET NULL,
Email VARCHAR(100),
Phone_No VARCHAR(15),
Salary NUMERIC(10,2),
Joining_Date DATE,
Shift_Time VARCHAR(50),
Address TEXT
);
9.Room:
CREATE TABLE Room (
Room_ID SERIAL PRIMARY KEY,
Room_Number VARCHAR(10) UNIQUE,
Department_ID INT REFERENCES Department(Department_ID) ON DELETE SET NULL,
Room_Type VARCHAR(50),
Capacity INT,
Status VARCHAR(20),
Availability BOOLEAN,
Floor_No INT,
Assigned_Patient INT REFERENCES Patient(Patient_ID) ON DELETE SET NULL,
Notes TEXT
);
10.Test:
CREATE TABLE Test (
Test_ID SERIAL PRIMARY KEY,
Patient_ID INT REFERENCES Patient(Patient_ID) ON DELETE CASCADE,
Doctor_ID INT REFERENCES Doctor(Doctor_ID) ON DELETE SET NULL,
Test_Type VARCHAR(100),
Test_Date DATE,
Result_File TEXT,
Status VARCHAR(20),
Lab_Technician VARCHAR(100),
Result_Date DATE,
Notes TEXT
);
2. Demonstrate Enforcement of Constraints
1. Valid Input – All constraints passed:
hospital_db=# insert into Patient(phone_no,email,state)
hospital_db-# values('8078523783','[email protected]','Kerala');
INSERT 0 1
hospital_db=# select * from Patient;
patient_id | first_name | last_name | gender | phone_no | email | date_of_birth | address | street | city
| state | emergency_contact | registration_date | blood_group
------------+------------+-----------+--------+------------+------------------+---------------+---------+--------+------+--------
+-------------------+-------------------+-------------
2| | | | 8078523783 | [email protected] | | | | | Kerala | |
2025-06-29 |
(1 row)
2. Violating NOT NULL constraint:
hospital_db=# INSERT INTO Patient (phone_no, email, state)
hospital_db-# VALUES (NULL, '[email protected]', 'Delhi');
ERROR: null value in column "phone_no" of relation "patient" violates not-null constraint
3. Violating UNIQUE constraint:
hospital_db=# insert into Patient(phone_no,email,state)
hospital_db-# values('9446625594','[email protected]','karnataka');
ERROR: duplicate key value violates unique constraint "patient_email_key"
DETAIL: Key (email)=([email protected]) already exists.
hospital_db=#
4. Violating CHECK constraint:
hospital_db=# INSERT INTO Patient (phone_no, email, gender)
hospital_db-# VALUES ('9876543210', '[email protected]', 'Unknown');
ERROR: new row for relation "patient" violates check constraint "patient_gender_check"
DETAIL: Failing row contains (7, null, null, Unknown, 9876543210, [email protected], null,
null, null, null, null, null, 2025-06-29, null).
hospital_db=#
5.Violating PRIMARY KEY (manually setting the ID):
hospital_db=# insert into Patient(patient_id,First_name,phone_no,email)
hospital_db-# values(2,'Riya','9495772289','[email protected]');
ERROR: duplicate key value violates unique constraint "patient_pkey"
DETAIL: Key (patient_id)=(2) already exists.
hospital_db=#
3. ALTER TABLE to Add Constraint
hospital_db=# alter table Doctor add constraint chk_gender check(gender
in('female','male','other'));
ALTER TABLE
hospital_db=# \d doctor
Table "public.doctor"
Column | Type | Collation | Nullable | Default
------------------+------------------------+-----------+----------+-------------------------------------------
doctor_id | integer | | not null | nextval('doctor_doctor_id_seq'::regclass)
name | character varying(100) | | |
gender | character varying(10) | | |
email | character varying(100) | | |
phone_no | character varying(15) | | |
joining_date | date | | |
specialization | character varying(100) | | |
department_id | integer | | |
consultation_fee | numeric(8,2) | | |
availability | boolean | | |
Indexes:
"doctor_pkey" PRIMARY KEY, btree (doctor_id)
"doctor_email_key" UNIQUE CONSTRAINT, btree (email)
"doctor_phone_no_key" UNIQUE CONSTRAINT, btree (phone_no)
Check constraints:
"chk_gender" CHECK (gender::text = ANY (ARRAY['female'::character varying,
'male'::character varying, 'other'::character varying]::text[]))
Foreign-key constraints:
"fk_department" FOREIGN KEY (department_id) REFERENCES department(department_id)
ON DELETE SET NULL
Referenced by:
TABLE "appointments" CONSTRAINT "appointments_doctor_id_fkey" FOREIGN KEY
(doctor_id) REFERENCES doctor(doctor_id) ON DELETE SET NULL
TABLE "prescription" CONSTRAINT "prescription_doctor_id_fkey" FOREIGN KEY
(doctor_id) REFERENCES doctor(doctor_id) ON DELETE SET NULL
TABLE "test" CONSTRAINT "test_doctor_id_fkey" FOREIGN KEY (doctor_id) REFERENCES
doctor(doctor_id) ON DELETE SET NULL
4. List of Constraints Enforced
Patient:
Constraint Type Column Details
PRIMARY KEY Patient_ID Auto-generated (SERIAL)
UNIQUE Phone_No No duplicate contact numbers
UNIQUE Email No duplicate emails
NOT NULL Phone_No Must be provided
CHECK Gender Must be 'Male', 'Female', 'Other'
DEFAULT Registration_Date Defaults to current date
Doctor:
Constraint Type Column Details
PRIMARY KEY Doctor_ID Auto-generated
UNIQUE Phone_No No duplicates
UNIQUE Email No duplicates
FOREIGN KEY Department_ID Refers to Department, ON DELETE SET NULL
CHECK Gender Only 'Male', 'Female', 'Other'
Appointments:
Constraint Type Column Details
PRIMARY KEY Appointment_ID Auto-generated
FOREIGN KEY Patient_ID Refers to Patient, ON DELETE CASCADE
FOREIGN KEY Doctor_ID Refers to Doctor, ON DELETE SET NULL
Medical Records:
Constraint Type Column Details
PRIMARY KEY Record_ID Auto-generated
FOREIGN KEY Patient_ID Refers to Patient, ON DELETE CASCADE
DEFAULT Date_Updated Current date
Billing:
Constraint Type Column Details
Refers to Appointments, ON DELETE SET
FOREIGN KEY Appointment_ID
NULL
FOREIGN KEY Patient_ID Refers to Patient, ON DELETE CASCADE
DEFAULT Billing_Date Defaults to current date
Prescription:
Constraint Type Column Details
PRIMARY KEY Prescription_ID Auto-generated
FOREIGN KEY Doctor_ID Refers to Doctor, ON DELETE SET NULL
FOREIGN KEY Patient_ID Refers to Patient, ON DELETE CASCADE
DEFAULT Date_Issued Current date
Department:
Constraint Type Column Details
PRIMARY KEY Department_ID Auto-generated
DEFAULT Created_At Current date
Staff:
Constraint
Column Details
Type
PRIMARY KEY Staff_ID Auto-generated
FOREIGN KEY Department_ID Refers to Department, ON DELETE SET NULL
Room:
Constraint
Column Details
Type
PRIMARY KEY Room_ID Auto-generated
UNIQUE Room_Number No duplicates
FOREIGN KEY Department_ID Refers to Department, ON DELETE SET NULL
FOREIGN KEY Assigned_Patient Refers to Patient, ON DELETE SET NULL
Test:
Constraint Type Column Details
PRIMARY KEY Test_ID Auto-generated
FOREIGN KEY Patient_ID Refers to Patient, ON DELETE CASCADE
FOREIGN KEY Doctor_ID Refers to Doctor, ON DELETE SET NULL
5. Drop a Constraint
hospital_db=# alter table Doctor drop constraint chk_gender;
ALTER TABLE
hospital_db=# \d Doctor
Table "public.doctor"
Column | Type | Collation | Nullable | Default
------------------+------------------------+-----------+----------+-------------------------------------------
doctor_id | integer | | not null | nextval('doctor_doctor_id_seq'::regclass)
name | character varying(100) | | |
gender | character varying(10) | | |
email | character varying(100) | | |
phone_no | character varying(15) | | |
joining_date | date | | |
specialization | character varying(100) | | |
department_id | integer | | |
consultation_fee | numeric(8,2) | | |
availability | boolean | | |
Indexes:
"doctor_pkey" PRIMARY KEY, btree (doctor_id)
"doctor_email_key" UNIQUE CONSTRAINT, btree (email)
"doctor_phone_no_key" UNIQUE CONSTRAINT, btree (phone_no)
Foreign-key constraints:
"fk_department" FOREIGN KEY (department_id) REFERENCES department(department_id) ON DELETE SET
NULL
Referenced by:
TABLE "appointments" CONSTRAINT "appointments_doctor_id_fkey" FOREIGN KEY (doctor_id) REFERENCES
doctor(doctor_id) ON DELETE SET NULL
TABLE "prescription" CONSTRAINT "prescription_doctor_id_fkey" FOREIGN KEY (doctor_id) REFERENCES
doctor(doctor_id) ON DELETE SET NULL
TABLE "test" CONSTRAINT "test_doctor_id_fkey" FOREIGN KEY (doctor_id) REFERENCES doctor(doctor_id)
ON DELETE SET NULL
6.Propagation of Changes (Data Integrity)
Parent table:
hospital_db=# INSERT INTO Patient (First_Name, Last_Name, Gender, Phone_No, Email, Date_of_Birth,
Emergency_Contact, Blood_Group, Street, City, State)
hospital_db-# VALUES ('John', 'Doe', 'Male', '9876543210', '[email protected]', '1990-01-01', '9999999999',
'O+', '12 Street', 'CityA', 'StateA');
INSERT 0 1
hospital_db-# ;
patient_id | first_name | last_name | gender | phone_no | email | date_of_birth | address | street |
city | state | emergency_contact | registration_date | blood_group
------------+------------+-----------+--------+------------+------------------+---------------+---------+-----------+-------+--------
+-------------------+-------------------+-------------
2| | | | 8078523783 | [email protected] | | | | | Kerala |
| 2025-06-29 |
5 | Siya | | | 9495115665 | [email protected] | | | | | | |
2025-06-29 |
8 | John | Doe | Male | 9876543210 | [email protected] | 1990-01-01 | | 12 Street |
CityA | StateA | 9999999999 | 2025-06-29 | O+
(3 rows)
Child table:
hospital_db=# INSERT INTO Appointments (Patient_ID, Doctor_ID, Mode, Consultation_Type, Status, Time_Slot,
Booking_Date, Appointment_Date, Reason)
hospital_db-# VALUES (8, NULL, 'Online', 'General', 'Booked', '10AM-11AM', CURRENT_DATE, CURRENT_DATE +
1, 'Routine Checkup');
INSERT 0 1
hospital_db=# select * from Appointments;
appointment_id | patient_id | doctor_id | mode | consultation_type | status | time_slot | booking_date |
appointment_date | reason
----------------+------------+-----------+--------+-------------------+--------+-----------+--------------+------------------
+-----------------
1| 8| | Online | General | Booked | 10AM-11AM | 2025-06-29 | 2025-06-30 |
Routine Checkup
Deleting patient_id=8 from Patient table(parent table):
hospital_db=# delete from Patient where patient_id=8;
DELETE 1
hospital_db=# select * from Patient;
patient_id | first_name | last_name | gender | phone_no | email | date_of_birth | address | street |
city | state | emergency_contact | registration_date | blood_group
------------+------------+-----------+--------+------------+------------------+---------------+---------+--------+------+--------
+-------------------+-------------------+-------------
2| | | | 8078523783 | [email protected] | | | | | Kerala |
| 2025-06-29 |
5 | Siya | | | 9495115665 | [email protected] | | | | | | |
2025-06-29 |
(2 rows)
Automatically deleted:
hospital_db=# select * from Appointments;
appointment_id | patient_id | doctor_id | mode | consultation_type | status | time_slot | booking_date |
appointment_date | reason
----------------+------------+-----------+------+-------------------+--------+-----------+--------------+------------------+--------
(0 rows)
7. DROP vs TRUNCATE
Drop:
hospital_db=# DROP TABLE Staff;
DROP TABLE
hospital_db=# TRUNCATE TABLE Staff;
ERROR: relation "staff" does not exist
Truncate:
hospital_db=# TRUNCATE TABLE Medical_records;
TRUNCATE TABLE