Hospital management system data model
This example models the core records of a hospital: patients and their insurance, doctors and departments, outpatient appointments, inpatient admissions to wards and beds, diagnoses, prescriptions and invoices.
Design notes
- Outpatient and inpatient care are separate. An
appointmentis a scheduled visit; anadmissionis a stay with a bed, an attending doctor and admission and discharge times. - Diagnoses can come from either.
diagnosislinks to the patient and, optionally, to the admission or the appointment where it was made. Codes use ICD-10. - Medications are a formulary.
prescriptionlinks a patient, a prescribing doctor and a medication, with dosage and dates. - Most patient data is PII or health data, and is flagged so it can be masked, encrypted or excluded from analytics. Real systems also need audit trails and consent records.
- Specialty and blood type are reference lists with their values.
This is a teaching example, not a clinical system: real hospital data follows standards such as HL7 FHIR and local regulations (for example HIPAA in the United States).
Diagram
Hospital Management System: 12 entities, 2 reference lists and 17 relationships. Each box is an entity with its attributes (PK marks the primary key); solid lines are relationships in crow's foot notation, dashed lines point to reference lists.
Open this model in EntityModel.com to explore it, change it and export it. Nothing is uploaded: the model travels in the link. Or download model.json.
Entities
| Entity | Type | Description | Primary Key | Display Attribute | Attributes |
|---|---|---|---|---|---|
| Admission | Entity | An inpatient stay, from admission to discharge. | admission_id | admitted_at | 6 |
| Appointment | Entity | A scheduled outpatient visit. | appointment_id | scheduled_at | 6 |
| Bed | Entity | A bed in a ward. | bed_id | bed_number | 4 |
| Department | Entity | A clinical department, such as Cardiology. | department_id | department_name | 3 |
| Diagnosis | Entity | A condition recorded for a patient during an admission or appointment. | diagnosis_id | description | 7 |
| Doctor | Entity | A physician on staff. | doctor_id | full_name | 6 |
| Insurance Provider | Entity | An insurance company that pays for care. | insurance_provider_id | provider_name | 2 |
| Invoice | Entity | A bill for an admission or appointment. | invoice_id | invoice_number | 8 |
| Medication | Entity | A drug in the hospital formulary. | medication_id | medication_name | 3 |
| Patient | Entity | A person who receives care. Holds personal and health data, so most attributes are PII. | patient_id | full_name | 9 |
| Prescription | Entity | A medication prescribed to a patient by a doctor. | prescription_id | dosage | 7 |
| Ward | Entity | An inpatient ward. | ward_id | ward_name | 3 |
| Blood Type | Reference | ABO and Rh blood types. | blood_type_code | blood_type_name | 2 |
| Specialty | Reference | Medical specialties. | specialty_code | specialty_name | 2 |
Attributes
Admission
An inpatient stay, from admission to discharge.
| Attribute | Data Type | Flags | Reference | Example | Description |
|---|---|---|---|---|---|
| admission_id | BIGINT | PK, Required | 88010 | ||
| patient_id | BIGINT | Required | 300451 | ||
| attending_doctor_id | INT | Required | 812 | ||
| bed_id | INT | Required | 6012 | ||
| admitted_at | TIMESTAMP | Label, Required | 2026-10-30T22:15:00Z | ||
| discharged_at | TIMESTAMP | Empty while admitted. |
Appointment
A scheduled outpatient visit.
| Attribute | Data Type | Flags | Reference | Example | Description |
|---|---|---|---|---|---|
| appointment_id | BIGINT | PK, Required | 1200045 | ||
| patient_id | BIGINT | Required | 300451 | ||
| doctor_id | INT | Required | 812 | ||
| scheduled_at | TIMESTAMP | Label, Required | 2026-11-12T09:30:00Z | ||
| status | STRING | Required | SCHEDULED | Scheduled, completed, cancelled or no-show. | |
| reason | STRING | PII | Chest pain follow-up |
Bed
A bed in a ward.
| Attribute | Data Type | Flags | Reference | Example | Description |
|---|---|---|---|---|---|
| bed_id | INT | PK, Required | 6012 | ||
| bed_number | STRING | Label, Required | CCU-12 | ||
| ward_id | INT | Required | 6 | ||
| is_occupied | BOOLEAN | Required | true |
Department
A clinical department, such as Cardiology.
| Attribute | Data Type | Flags | Reference | Example | Description |
|---|---|---|---|---|---|
| department_id | INT | PK, Required | 4 | ||
| department_name | STRING | Label, Required | Cardiology | ||
| floor | INT | 3 |
Diagnosis
A condition recorded for a patient during an admission or appointment.
| Attribute | Data Type | Flags | Reference | Example | Description |
|---|---|---|---|---|---|
| diagnosis_id | BIGINT | PK, Required | 500912 | ||
| patient_id | BIGINT | Required | 300451 | ||
| admission_id | BIGINT | 88010 | |||
| appointment_id | BIGINT | ||||
| icd10_code | STRING | Required, PII | I21.4 | ICD-10 diagnosis code. | |
| description | STRING | Label, Required, PII | Non-ST elevation myocardial infarction | ||
| diagnosed_at | TIMESTAMP | Required | 2026-10-31T08:00:00Z |
Doctor
A physician on staff.
| Attribute | Data Type | Flags | Reference | Example | Description |
|---|---|---|---|---|---|
| doctor_id | INT | PK, Required | 812 | ||
| license_number | STRING | Required | MD-778201 | ||
| full_name | STRING | Label, Required, PII | Dr. Aisha Patel | ||
| specialty_code | REFERENCE | Required | → specialty.specialty_code | CARD | |
| department_id | INT | Required | 4 | ||
| phone | STRING | PII | +1 555 0123 |
Insurance Provider
An insurance company that pays for care.
| Attribute | Data Type | Flags | Reference | Example | Description |
|---|---|---|---|---|---|
| insurance_provider_id | INT | PK, Required | 8 | ||
| provider_name | STRING | Label, Required | Blue Ridge Health Plan |
Invoice
A bill for an admission or appointment.
| Attribute | Data Type | Flags | Reference | Example | Description |
|---|---|---|---|---|---|
| invoice_id | BIGINT | PK, Required | 61022 | ||
| invoice_number | STRING | Label, Required | INV-2026-061022 | ||
| patient_id | BIGINT | Required | 300451 | ||
| admission_id | BIGINT | 88010 | |||
| total_amount | DECIMAL(12,2) | Required | 18450.00 | ||
| insurance_covered_amount | DECIMAL(12,2) | 15000.00 | |||
| issued_on | DATE | Required | 2026-11-04 | ||
| paid_on | DATE |
Medication
A drug in the hospital formulary.
| Attribute | Data Type | Flags | Reference | Example | Description |
|---|---|---|---|---|---|
| medication_id | INT | PK, Required | 1450 | ||
| medication_name | STRING | Label, Required | Atorvastatin 40 mg | ||
| form | STRING | Tablet |
Patient
A person who receives care. Holds personal and health data, so most attributes are PII.
| Attribute | Data Type | Flags | Reference | Example | Description |
|---|---|---|---|---|---|
| patient_id | BIGINT | PK, Required | 300451 | ||
| medical_record_number | STRING | Required, PII | MRN-0300451 | MRN. | |
| full_name | STRING | Label, Required, PII | Daniel Brooks | ||
| date_of_birth | DATE | Required, PII | 1975-02-14 | ||
| sex | STRING | PII | M | ||
| phone | STRING | PII | +1 555 0190 | ||
| blood_type_code | REFERENCE | PII | → blood_type.blood_type_code | O+ | |
| insurance_provider_id | INT | 8 | |||
| insurance_member_id | STRING | PII | XGH4410021 |
Prescription
A medication prescribed to a patient by a doctor.
| Attribute | Data Type | Flags | Reference | Example | Description |
|---|---|---|---|---|---|
| prescription_id | BIGINT | PK, Required | 730055 | ||
| patient_id | BIGINT | Required | 300451 | ||
| doctor_id | INT | Required | 812 | ||
| medication_id | INT | Required | 1450 | ||
| dosage | STRING | Label, Required | 40 mg once daily | ||
| start_date | DATE | Required | 2026-11-01 | ||
| end_date | DATE |
Ward
An inpatient ward.
| Attribute | Data Type | Flags | Reference | Example | Description |
|---|---|---|---|---|---|
| ward_id | INT | PK, Required | 6 | ||
| ward_name | STRING | Label, Required | Cardiac Care Unit | ||
| department_id | INT | Required | 4 |
Blood Type
ABO and Rh blood types.
| Attribute | Data Type | Flags | Reference | Example | Description |
|---|---|---|---|---|---|
| blood_type_code | STRING | PK, Required | O+ | ||
| blood_type_name | STRING | Label, Required | O positive |
Specialty
Medical specialties.
| Attribute | Data Type | Flags | Reference | Example | Description |
|---|---|---|---|---|---|
| specialty_code | STRING | PK, Required | CARD | ||
| specialty_name | STRING | Label, Required | Cardiology |
Relationships
| Relationship | Source | Target | Cardinality | Forward Label | Reverse Label | Key | Description |
|---|---|---|---|---|---|---|---|
| insured_by | Patient | Insurance Provider | N:1 | Insured By | Insures | patient.insurance_provider_id | |
| doctor_in | Doctor | Department | N:1 | Works In | Staffed By | doctor.department_id | |
| appointment_for | Appointment | Patient | N:1 | For | Has Appointment | appointment.patient_id | |
| appointment_with | Appointment | Doctor | N:1 | With | Sees | appointment.doctor_id | |
| ward_of | Ward | Department | N:1 | Run By | Runs | ward.department_id | |
| bed_in | Bed | Ward | N:1 | In | Has Bed | bed.ward_id | |
| admits | Admission | Patient | N:1 | Admits | Admitted In | admission.patient_id | |
| attended_by | Admission | Doctor | N:1 | Attended By | Attends | admission.attending_doctor_id | |
| assigned_bed | Admission | Bed | N:1 | Assigned | Occupied In | admission.bed_id | |
| diagnosis_of | Diagnosis | Patient | N:1 | Of | Diagnosed With | diagnosis.patient_id | |
| made_during_admission | Diagnosis | Admission | N:1 | During | Has Diagnosis | diagnosis.admission_id | |
| made_during_appointment | Diagnosis | Appointment | N:1 | During | Has Diagnosis | diagnosis.appointment_id | |
| prescribed_to | Prescription | Patient | N:1 | Prescribed To | Receives | prescription.patient_id | |
| prescribed_by | Prescription | Doctor | N:1 | Prescribed By | Prescribes | prescription.doctor_id | |
| prescribes | Prescription | Medication | N:1 | Of | Prescribed In | prescription.medication_id | |
| billed_to | Invoice | Patient | N:1 | Billed To | Billed | invoice.patient_id | |
| bills_admission | Invoice | Admission | N:1 | Bills | Billed In | invoice.admission_id |
Reference data
Blood Type
8 values · Source: Example values
| blood_type_code | blood_type_name |
|---|---|
| A+ | A positive |
| A- | A negative |
| B+ | B positive |
| B- | B negative |
| AB+ | AB positive |
| AB- | AB negative |
| O+ | O positive |
| O- | O negative |
Specialty
6 values · Source: Example values
| specialty_code | specialty_name |
|---|---|
| CARD | Cardiology |
| NEUR | Neurology |
| ORTH | Orthopedics |
| PED | Pediatrics |
| ONC | Oncology |
| EM | Emergency medicine |
SQL DDL (PostgreSQL)
Generated from the model. In the app, Export → Code also writes MySQL, Snowflake and Databricks DDL, DBML, dbt schema.yml and data contracts.
-- Hospital Management System — data model
-- PostgreSQL DDL, generated 2026-11-03
-- Made with EntityModel.com
-- Reference list: Specialty
CREATE TABLE specialty (
specialty_code TEXT NOT NULL,
specialty_name TEXT NOT NULL,
PRIMARY KEY (specialty_code)
);
COMMENT ON TABLE specialty IS 'Medical specialties.';
-- Reference list: Blood Type
CREATE TABLE blood_type (
blood_type_code TEXT NOT NULL,
blood_type_name TEXT NOT NULL,
PRIMARY KEY (blood_type_code)
);
COMMENT ON TABLE blood_type IS 'ABO and Rh blood types.';
CREATE TABLE patient (
patient_id BIGINT NOT NULL,
medical_record_number TEXT NOT NULL,
full_name TEXT NOT NULL,
date_of_birth DATE NOT NULL,
sex TEXT,
phone TEXT,
blood_type_code TEXT,
insurance_provider_id INTEGER,
insurance_member_id TEXT,
PRIMARY KEY (patient_id)
);
COMMENT ON TABLE patient IS 'A person who receives care. Holds personal and health data, so most attributes are PII.';
COMMENT ON COLUMN patient.medical_record_number IS 'MRN.';
CREATE TABLE department (
department_id INTEGER NOT NULL,
department_name TEXT NOT NULL,
floor INTEGER,
PRIMARY KEY (department_id)
);
COMMENT ON TABLE department IS 'A clinical department, such as Cardiology.';
CREATE TABLE doctor (
doctor_id INTEGER NOT NULL,
license_number TEXT NOT NULL,
full_name TEXT NOT NULL,
specialty_code TEXT NOT NULL,
department_id INTEGER NOT NULL,
phone TEXT,
PRIMARY KEY (doctor_id)
);
COMMENT ON TABLE doctor IS 'A physician on staff.';
CREATE TABLE appointment (
appointment_id BIGINT NOT NULL,
patient_id BIGINT NOT NULL,
doctor_id INTEGER NOT NULL,
scheduled_at TIMESTAMP NOT NULL,
status TEXT NOT NULL,
reason TEXT,
PRIMARY KEY (appointment_id)
);
COMMENT ON TABLE appointment IS 'A scheduled outpatient visit.';
COMMENT ON COLUMN appointment.status IS 'Scheduled, completed, cancelled or no-show.';
CREATE TABLE ward (
ward_id INTEGER NOT NULL,
ward_name TEXT NOT NULL,
department_id INTEGER NOT NULL,
PRIMARY KEY (ward_id)
);
COMMENT ON TABLE ward IS 'An inpatient ward.';
CREATE TABLE bed (
bed_id INTEGER NOT NULL,
bed_number TEXT NOT NULL,
ward_id INTEGER NOT NULL,
is_occupied BOOLEAN NOT NULL,
PRIMARY KEY (bed_id)
);
COMMENT ON TABLE bed IS 'A bed in a ward.';
CREATE TABLE admission (
admission_id BIGINT NOT NULL,
patient_id BIGINT NOT NULL,
attending_doctor_id INTEGER NOT NULL,
bed_id INTEGER NOT NULL,
admitted_at TIMESTAMP NOT NULL,
discharged_at TIMESTAMP,
PRIMARY KEY (admission_id)
);
COMMENT ON TABLE admission IS 'An inpatient stay, from admission to discharge.';
COMMENT ON COLUMN admission.discharged_at IS 'Empty while admitted.';
CREATE TABLE diagnosis (
diagnosis_id BIGINT NOT NULL,
patient_id BIGINT NOT NULL,
admission_id BIGINT,
appointment_id BIGINT,
icd10_code TEXT NOT NULL,
description TEXT NOT NULL,
diagnosed_at TIMESTAMP NOT NULL,
PRIMARY KEY (diagnosis_id)
);
COMMENT ON TABLE diagnosis IS 'A condition recorded for a patient during an admission or appointment.';
COMMENT ON COLUMN diagnosis.icd10_code IS 'ICD-10 diagnosis code.';
CREATE TABLE medication (
medication_id INTEGER NOT NULL,
medication_name TEXT NOT NULL,
form TEXT,
PRIMARY KEY (medication_id)
);
COMMENT ON TABLE medication IS 'A drug in the hospital formulary.';
CREATE TABLE prescription (
prescription_id BIGINT NOT NULL,
patient_id BIGINT NOT NULL,
doctor_id INTEGER NOT NULL,
medication_id INTEGER NOT NULL,
dosage TEXT NOT NULL,
start_date DATE NOT NULL,
end_date DATE,
PRIMARY KEY (prescription_id)
);
COMMENT ON TABLE prescription IS 'A medication prescribed to a patient by a doctor.';
CREATE TABLE invoice (
invoice_id BIGINT NOT NULL,
invoice_number TEXT NOT NULL,
patient_id BIGINT NOT NULL,
admission_id BIGINT,
total_amount NUMERIC(12,2) NOT NULL,
insurance_covered_amount NUMERIC(12,2),
issued_on DATE NOT NULL,
paid_on DATE,
PRIMARY KEY (invoice_id)
);
COMMENT ON TABLE invoice IS 'A bill for an admission or appointment.';
CREATE TABLE insurance_provider (
insurance_provider_id INTEGER NOT NULL,
provider_name TEXT NOT NULL,
PRIMARY KEY (insurance_provider_id)
);
COMMENT ON TABLE insurance_provider IS 'An insurance company that pays for care.';
-- Keys between tables
ALTER TABLE patient ADD CONSTRAINT uq_patient_medical_record_number UNIQUE (medical_record_number);
ALTER TABLE doctor ADD CONSTRAINT uq_doctor_license_number UNIQUE (license_number);
ALTER TABLE invoice ADD CONSTRAINT uq_invoice_invoice_number UNIQUE (invoice_number);
ALTER TABLE patient ADD CONSTRAINT fk_patient_blood_type_code FOREIGN KEY (blood_type_code) REFERENCES blood_type (blood_type_code);
ALTER TABLE doctor ADD CONSTRAINT fk_doctor_specialty_code FOREIGN KEY (specialty_code) REFERENCES specialty (specialty_code);
ALTER TABLE patient ADD CONSTRAINT fk_insured_by FOREIGN KEY (insurance_provider_id) REFERENCES insurance_provider (insurance_provider_id);
ALTER TABLE doctor ADD CONSTRAINT fk_doctor_in FOREIGN KEY (department_id) REFERENCES department (department_id);
ALTER TABLE appointment ADD CONSTRAINT fk_appointment_for FOREIGN KEY (patient_id) REFERENCES patient (patient_id);
ALTER TABLE appointment ADD CONSTRAINT fk_appointment_with FOREIGN KEY (doctor_id) REFERENCES doctor (doctor_id);
ALTER TABLE ward ADD CONSTRAINT fk_ward_of FOREIGN KEY (department_id) REFERENCES department (department_id);
ALTER TABLE bed ADD CONSTRAINT fk_bed_in FOREIGN KEY (ward_id) REFERENCES ward (ward_id);
ALTER TABLE admission ADD CONSTRAINT fk_admits FOREIGN KEY (patient_id) REFERENCES patient (patient_id);
ALTER TABLE admission ADD CONSTRAINT fk_attended_by FOREIGN KEY (attending_doctor_id) REFERENCES doctor (doctor_id);
ALTER TABLE admission ADD CONSTRAINT fk_assigned_bed FOREIGN KEY (bed_id) REFERENCES bed (bed_id);
ALTER TABLE diagnosis ADD CONSTRAINT fk_diagnosis_of FOREIGN KEY (patient_id) REFERENCES patient (patient_id);
ALTER TABLE diagnosis ADD CONSTRAINT fk_made_during_admission FOREIGN KEY (admission_id) REFERENCES admission (admission_id);
ALTER TABLE diagnosis ADD CONSTRAINT fk_made_during_appointment FOREIGN KEY (appointment_id) REFERENCES appointment (appointment_id);
ALTER TABLE prescription ADD CONSTRAINT fk_prescribed_to FOREIGN KEY (patient_id) REFERENCES patient (patient_id);
ALTER TABLE prescription ADD CONSTRAINT fk_prescribed_by FOREIGN KEY (doctor_id) REFERENCES doctor (doctor_id);
ALTER TABLE prescription ADD CONSTRAINT fk_prescribes FOREIGN KEY (medication_id) REFERENCES medication (medication_id);
ALTER TABLE invoice ADD CONSTRAINT fk_billed_to FOREIGN KEY (patient_id) REFERENCES patient (patient_id);
ALTER TABLE invoice ADD CONSTRAINT fk_bills_admission FOREIGN KEY (admission_id) REFERENCES admission (admission_id);
-- Reference values
INSERT INTO specialty (specialty_code, specialty_name) VALUES
('CARD', 'Cardiology'),
('NEUR', 'Neurology'),
('ORTH', 'Orthopedics'),
('PED', 'Pediatrics'),
('ONC', 'Oncology'),
('EM', 'Emergency medicine');
INSERT INTO blood_type (blood_type_code, blood_type_name) VALUES
('A+', 'A positive'),
('A-', 'A negative'),
('B+', 'B positive'),
('B-', 'B negative'),
('AB+', 'AB positive'),
('AB-', 'AB negative'),
('O+', 'O positive'),
('O-', 'O negative');
Mermaid
Paste into a mermaid code block on GitHub, GitLab or Notion to show the diagram there.
---
title: Hospital Management System
---
%% Made with EntityModel.com
erDiagram
patient {
bigint patient_id PK "Patient ID"
string medical_record_number "MRN."
string full_name "Full Name"
date date_of_birth "Date Of Birth"
string sex "Sex"
string phone "Phone"
string blood_type_code FK "Blood Type Code"
int insurance_provider_id FK "Insurance Provider ID"
string insurance_member_id "Insurance Member ID"
}
department {
int department_id PK "Department ID"
string department_name "Department Name"
int floor "Floor"
}
doctor {
int doctor_id PK "Doctor ID"
string license_number "License Number"
string full_name "Full Name"
string specialty_code FK "Specialty Code"
int department_id FK "Department ID"
string phone "Phone"
}
appointment {
bigint appointment_id PK "Appointment ID"
bigint patient_id FK "Patient ID"
int doctor_id FK "Doctor ID"
timestamp scheduled_at "Scheduled At"
string status "Scheduled, completed, cancelled or no-show."
string reason "Reason"
}
ward {
int ward_id PK "Ward ID"
string ward_name "Ward Name"
int department_id FK "Department ID"
}
bed {
int bed_id PK "Bed ID"
string bed_number "Bed Number"
int ward_id FK "Ward ID"
boolean is_occupied "Is Occupied"
}
admission {
bigint admission_id PK "Admission ID"
bigint patient_id FK "Patient ID"
int attending_doctor_id FK "Attending Doctor ID"
int bed_id FK "Bed ID"
timestamp admitted_at "Admitted At"
timestamp discharged_at "Empty while admitted."
}
diagnosis {
bigint diagnosis_id PK "Diagnosis ID"
bigint patient_id FK "Patient ID"
bigint admission_id FK "Admission ID"
bigint appointment_id FK "Appointment ID"
string icd10_code "ICD-10 diagnosis code."
string description "Description"
timestamp diagnosed_at "Diagnosed At"
}
medication {
int medication_id PK "Medication ID"
string medication_name "Medication Name"
string form "Form"
}
prescription {
bigint prescription_id PK "Prescription ID"
bigint patient_id FK "Patient ID"
int doctor_id FK "Doctor ID"
int medication_id FK "Medication ID"
string dosage "Dosage"
date start_date "Start Date"
date end_date "End Date"
}
invoice {
bigint invoice_id PK "Invoice ID"
string invoice_number "Invoice Number"
bigint patient_id FK "Patient ID"
bigint admission_id FK "Admission ID"
decimal total_amount "Total Amount"
decimal insurance_covered_amount "Insurance Covered Amount"
date issued_on "Issued On"
date paid_on "Paid On"
}
insurance_provider {
int insurance_provider_id PK "Insurance Provider ID"
string provider_name "Provider Name"
}
specialty {
string specialty_code PK "Specialty Code"
string specialty_name "Specialty Name"
}
blood_type {
string blood_type_code PK "Blood Type Code"
string blood_type_name "Blood Type Name"
}
patient }o--|| insurance_provider : "Insured By"
doctor }o--|| department : "Works In"
appointment }o--|| patient : "For"
appointment }o--|| doctor : "With"
ward }o--|| department : "Run By"
bed }o--|| ward : "In"
admission }o--|| patient : "Admits"
admission }o--|| doctor : "Attended By"
admission }o--|| bed : "Assigned"
diagnosis }o--|| patient : "Of"
diagnosis }o--|| admission : "During"
diagnosis }o--|| appointment : "During"
prescription }o--|| patient : "Prescribed To"
prescription }o--|| doctor : "Prescribed By"
prescription }o--|| medication : "Of"
invoice }o--|| patient : "Billed To"
invoice }o--|| admission : "Bills"
patient }o..|| blood_type : "Blood Type Code"
doctor }o..|| specialty : "Specialty Code"
Frequently asked questions
What tables are in a hospital management system database?
Typically patient, doctor, department, appointment, admission, ward, bed, diagnosis, medication, prescription, invoice and insurance provider, with lookup tables such as specialty and blood type.
How do you model inpatient admissions and beds?
An admission links a patient to a bed and an attending doctor, with admitted and discharged timestamps. Beds belong to wards, and wards to departments, so occupancy can be reported at each level.