| 1 | | = Phase P2: Logical and Physical Design (DDL & DML) |
| 2 | | |
| 3 | | == Purpose and Scope of Phase P2 |
| 4 | | |
| 5 | | The objective of Phase P2 is to formally transform the conceptual ER model defined in Phase P1 |
| 6 | | into a logical and physical relational database design. |
| 7 | | |
| 8 | | This transformation is required because an ER model is descriptive and conceptual, |
| 9 | | while a relational database requires a precise formal structure. |
| 10 | | Therefore, every conceptual element identified in Phase P1 must be translated |
| 11 | | into relational constructs that preserve its meaning and constraints. |
| 12 | | |
| 13 | | All decisions in this phase are strictly derived from: |
| 14 | | 1) the ER model structure, |
| 15 | | 2) the cardinalities defined in Phase P1, |
| 16 | | 3) the real-world semantics of the wedding planning domain, |
| 17 | | and not from arbitrary or intuitive assumptions. |
| 18 | | |
| 19 | | |
| 20 | | == Basis for the ER-to-Relational Transformation |
| 21 | | |
| 22 | | The transformation process follows established ER-to-relational mapping rules. |
| 23 | | These rules are necessary because relational databases do not support ER constructs directly. |
| 24 | | |
| 25 | | The following principles were applied, each based on a specific limitation or requirement |
| 26 | | of the relational model: |
| 27 | | |
| 28 | | * Principle 1: Strong entities must be mapped to separate tables. |
| 29 | | This follows from the definition of a strong entity, which has an independent existence |
| 30 | | and must therefore be stored independently in the database. |
| 31 | | |
| 32 | | * Principle 2: Each entity must have a primary key. |
| 33 | | This requirement follows from entity integrity rules in relational theory, |
| 34 | | which state that each tuple must be uniquely identifiable. |
| 35 | | |
| 36 | | * Principle 3: Relationships must be mapped according to their cardinality. |
| 37 | | Since relational databases represent relationships through references, |
| 38 | | the placement of foreign keys is determined by the cardinality of the relationship. |
| 39 | | |
| 40 | | |
| 41 | | == Mapping of Entities |
| 42 | | |
| 43 | | Each entity identified in the ER model was mapped directly to a relational table. |
| 44 | | This decision is justified because each entity represents a real-world object |
| 45 | | with its own attributes and independent lifecycle. |
| 46 | | |
| 47 | | For example: |
| 48 | | The entity User represents a real system user and therefore requires its own table. |
| 49 | | Its identifier (user_id) is mapped as the primary key to ensure uniqueness. |
| 50 | | |
| 51 | | This reasoning applies equally to Wedding, Venue, Photographer, Band, Registrar, Event, Guest, and other entities. |
| 52 | | |
| 53 | | |
| 54 | | == Mapping of Relationships Based on Cardinality |
| 55 | | |
| 56 | | === One-to-Many (1:N) Relationships |
| 57 | | |
| 58 | | In a one-to-many relationship, one instance of an entity can be associated |
| 59 | | with multiple instances of another entity. |
| 60 | | |
| 61 | | According to relational mapping rules, such relationships are implemented |
| 62 | | by placing a foreign key in the table on the many-side of the relationship. |
| 63 | | This is necessary because the many-side depends on the existence of the one-side. |
| 64 | | |
| 65 | | Example: |
| 66 | | A Wedding can have multiple Events, but each Event belongs to exactly one Wedding. |
| 67 | | Therefore, wedding_id is stored as a foreign key in the Event table. |
| 68 | | This directly enforces the cardinality defined in the ER model. |
| 69 | | |
| 70 | | |
| 71 | | === Many-to-Many (N:M) Relationships |
| 72 | | |
| 73 | | Relational databases cannot represent N:M relationships directly. |
| 74 | | If such a relationship were implemented without an intermediate table, |
| 75 | | it would violate first normal form. |
| 76 | | |
| 77 | | Therefore, every N:M relationship in the ER model was transformed |
| 78 | | into an associative table containing foreign keys referencing the participating entities. |
| 79 | | |
| 80 | | Example: |
| 81 | | A Wedding can involve multiple Bands, and a Band can perform at multiple Weddings. |
| 82 | | This relationship was therefore transformed into the Band_Booking table, |
| 83 | | which references both Wedding and Band. |
| 84 | | The presence of additional attributes (date, time, status) further confirms |
| 85 | | that the relationship itself has properties and must be modeled as a separate entity. |
| 86 | | |
| 87 | | |
| 88 | | === One-to-One (1:1) Relationships |
| 89 | | |
| 90 | | One-to-one relationships require special handling because both entities |
| 91 | | have equal cardinality. |
| 92 | | |
| 93 | | In such cases, placing a UNIQUE foreign key in one of the participating tables |
| 94 | | is sufficient to preserve the relationship without redundancy. |
| 95 | | |
| 96 | | Example: |
| 97 | | The ER model specifies a 1:1 relationship between Wedding and Church. |
| 98 | | This reflects the real-world rule that a wedding can be held in only one church, |
| 99 | | and a church instance in this context is associated with only one wedding. |
| 100 | | |
| 101 | | This relationship is implemented by placing a UNIQUE wedding_id foreign key |
| 102 | | in the Church table. |
| 103 | | The UNIQUE constraint enforces the 1:1 cardinality explicitly at the database level. |
| 104 | | |
| 105 | | |
| 106 | | == Derivation of the Relational Schema |
| 107 | | |
| 108 | | Based on the transformation rules described above, |
| 109 | | the following relational schema was derived. |
| 110 | | |
| 111 | | Each relation corresponds either to: |
| 112 | | - a strong entity, or |
| 113 | | - an associative entity derived from an N:M relationship. |
| 114 | | |
| 115 | | (User, Wedding, Church, Priest, Venue_Type, Venue, Venue_Booking, |
| 116 | | Photographer, Photographer_Booking, Band, Band_Booking, |
| 117 | | Registrar, Registrar_Booking, Event, Guest, Event_RSVP, Attendance) |
| 118 | | |
| 119 | | No table exists without a direct conceptual origin in the ER model. |
| 120 | | |
| 121 | | |
| 122 | | == Data Integrity as a Consequence of the Model |
| 123 | | |
| 124 | | Data integrity constraints were not added arbitrarily, |
| 125 | | but derived directly from the structure and semantics of the model. |
| 126 | | |
| 127 | | === Entity Integrity |
| 128 | | |
| 129 | | Primary keys ensure that each entity instance is uniquely identifiable. |
| 130 | | Without primary keys, entities could not be referenced reliably, |
| 131 | | which would contradict the definition of an entity in the ER model. |
| 132 | | |
| 133 | | |
| 134 | | === Referential Integrity |
| 135 | | |
| 136 | | Foreign key constraints ensure that relationships between entities remain valid. |
| 137 | | A record that references another entity cannot exist unless that entity exists. |
| 138 | | |
| 139 | | For example: |
| 140 | | A booking without a corresponding wedding would have no real-world meaning. |
| 141 | | Therefore, foreign keys are mandatory to prevent invalid references. |
| 142 | | |
| 143 | | Cascading actions are used to maintain consistency when parent records are updated or removed. |
| 144 | | This reflects the dependency relationships already present in the ER model. |
| 145 | | |
| 146 | | |
| 147 | | === Business Logic Constraints |
| 148 | | |
| 149 | | Certain rules cannot be captured through keys alone. |
| 150 | | These rules are derived from real-world constraints and are enforced using CHECK and UNIQUE constraints. |
| 151 | | |
| 152 | | Examples: |
| 153 | | |
| 154 | | * Time constraints: |
| 155 | | An event or booking cannot end before it starts. |
| 156 | | This rule is enforced using CHECK (end_time > start_time), |
| 157 | | which directly reflects temporal logic in the real world. |
| 158 | | |
| 159 | | * Domain constraints: |
| 160 | | Attributes such as price and capacity must be positive. |
| 161 | | Negative values would contradict the meaning of these attributes. |
| 162 | | |
| 163 | | * Cardinality constraints: |
| 164 | | UNIQUE constraints enforce restrictions such as one church per wedding. |
| 165 | | This is a direct implementation of ER cardinality constraints. |
| 166 | | |
| 167 | | These rules are enforced at the database level to ensure correctness |
| 168 | | independently of application logic. |
| 169 | | |
| 170 | | |
| 171 | | == Relational Diagram |
| 172 | | |
| 173 | | The relational diagram was generated directly from the implemented schema using DBeaver. |
| 174 | | Because the diagram is generated from the actual database objects, |
| 175 | | it serves as a formal verification of the relational model. |
| 176 | | |
| 177 | | The diagram visually confirms: |
| 178 | | - correct primary and foreign key placement, |
| 179 | | - correct cardinalities, |
| 180 | | - consistency with the relational schema derived from the ER model. |
| 181 | | |
| 182 | | [[Image(db_202526z_va_prj_wedding_planner v.2 - project.png)]] |
| 183 | | |
| 184 | | |
| 185 | | == DDL and DML Implementation |
| 186 | | |
| 187 | | The logical and physical design is implemented using two SQL scripts: |
| 188 | | |
| 189 | | The DDL script defines the database structure and all integrity constraints. |
| 190 | | The DML script inserts sample data that complies with these constraints. |
| 191 | | |
| 192 | | The successful execution of the DML script serves as additional evidence |
| 193 | | that the relational design correctly enforces the intended rules. |
| 194 | | |
| 195 | | [[attachment:schema_creation.sql|DDL Script]] |
| 196 | | |
| 197 | | [[attachment:data_load.sql|DML Script]] |
| | 1 | = Relational Design |
| | 2 | |
| | 3 | == Description |
| | 4 | This page describes the relational database design of the Wedding Planner system. The relational model is derived directly from the final ER model and defines the database tables, their attributes, primary keys, foreign keys, and integrity constraints. The design ensures data consistency, avoids redundancy, and supports all system requirements. |
| | 5 | |
| | 6 | == Relational Schema |
| | 7 | |
| | 8 | == Table: user |
| | 9 | Stores registered users who organize weddings. |
| | 10 | |
| | 11 | user( |
| | 12 | user_id PK, |
| | 13 | first_name, |
| | 14 | last_name, |
| | 15 | email UNIQUE, |
| | 16 | phone_number, |
| | 17 | gender, |
| | 18 | birthday |
| | 19 | ) |
| | 20 | |
| | 21 | == Table: wedding |
| | 22 | Represents weddings created and managed by users. Acts as the central table of the system. |
| | 23 | |
| | 24 | wedding( |
| | 25 | wedding_id PK, |
| | 26 | date, |
| | 27 | budget, |
| | 28 | notes, |
| | 29 | type, |
| | 30 | status, |
| | 31 | user_id FK → user(user_id) |
| | 32 | ) |
| | 33 | |
| | 34 | == Table: church |
| | 35 | Represents churches where wedding ceremonies can take place. Each wedding can be associated with one church. |
| | 36 | |
| | 37 | church( |
| | 38 | church_id PK, |
| | 39 | name, |
| | 40 | location, |
| | 41 | contact, |
| | 42 | wedding_id FK → wedding(wedding_id) UNIQUE |
| | 43 | ) |
| | 44 | |
| | 45 | == Table: priest |
| | 46 | Represents priests associated with churches. |
| | 47 | |
| | 48 | priest( |
| | 49 | priest_id PK, |
| | 50 | name, |
| | 51 | contact, |
| | 52 | church_id FK → church(church_id) |
| | 53 | ) |
| | 54 | |
| | 55 | == Table: event |
| | 56 | Represents events that are part of a wedding (e.g. ceremony, reception). |
| | 57 | |
| | 58 | event( |
| | 59 | event_id PK, |
| | 60 | event_type, |
| | 61 | date, |
| | 62 | start_time, |
| | 63 | end_time, |
| | 64 | status, |
| | 65 | wedding_id FK → wedding(wedding_id) |
| | 66 | ) |
| | 67 | |
| | 68 | == Table: guest |
| | 69 | Represents guests invited to a wedding. |
| | 70 | |
| | 71 | guest( |
| | 72 | guest_id PK, |
| | 73 | first_name, |
| | 74 | last_name, |
| | 75 | email, |
| | 76 | wedding_id FK → wedding(wedding_id) |
| | 77 | ) |
| | 78 | |
| | 79 | == Table: event_rsvp |
| | 80 | Stores guest responses to event invitations. Resolves the many-to-many relationship between guest and event. |
| | 81 | |
| | 82 | event_rsvp( |
| | 83 | response_id PK, |
| | 84 | status, |
| | 85 | response_date, |
| | 86 | guest_id FK → guest(guest_id), |
| | 87 | event_id FK → event(event_id), |
| | 88 | UNIQUE (guest_id, event_id) |
| | 89 | ) |
| | 90 | |
| | 91 | == Table: attendance |
| | 92 | Represents actual guest participation in events, including seating and role information. |
| | 93 | |
| | 94 | attendance( |
| | 95 | attendance_id PK, |
| | 96 | status, |
| | 97 | table_number, |
| | 98 | role, |
| | 99 | guest_id FK → guest(guest_id), |
| | 100 | event_id FK → event(event_id), |
| | 101 | UNIQUE (guest_id, event_id) |
| | 102 | ) |
| | 103 | |
| | 104 | == Table: venue_type |
| | 105 | Defines categories of venues. |
| | 106 | |
| | 107 | venue_type( |
| | 108 | type_id PK, |
| | 109 | type_name UNIQUE |
| | 110 | ) |
| | 111 | |
| | 112 | == Table: venue |
| | 113 | Represents venues available for wedding events. |
| | 114 | |
| | 115 | venue( |
| | 116 | venue_id PK, |
| | 117 | name, |
| | 118 | location, |
| | 119 | city, |
| | 120 | address, |
| | 121 | capacity, |
| | 122 | menu, |
| | 123 | phone_number, |
| | 124 | price_per_guest, |
| | 125 | type_id FK → venue_type(type_id) |
| | 126 | ) |
| | 127 | |
| | 128 | == Table: venue_booking |
| | 129 | Represents reservations of venues for weddings. |
| | 130 | |
| | 131 | venue_booking( |
| | 132 | booking_id PK, |
| | 133 | date, |
| | 134 | start_time, |
| | 135 | end_time, |
| | 136 | status, |
| | 137 | price, |
| | 138 | venue_id FK → venue(venue_id), |
| | 139 | wedding_id FK → wedding(wedding_id) |
| | 140 | ) |
| | 141 | |
| | 142 | == Table: photographer |
| | 143 | Represents photographers available for weddings. |
| | 144 | |
| | 145 | photographer( |
| | 146 | photographer_id PK, |
| | 147 | name, |
| | 148 | email UNIQUE, |
| | 149 | phone_number, |
| | 150 | price_per_hour |
| | 151 | ) |
| | 152 | |
| | 153 | == Table: photographer_booking |
| | 154 | Represents photographer reservations for weddings. |
| | 155 | |
| | 156 | photographer_booking( |
| | 157 | booking_id PK, |
| | 158 | date, |
| | 159 | start_time, |
| | 160 | end_time, |
| | 161 | status, |
| | 162 | photographer_id FK → photographer(photographer_id), |
| | 163 | wedding_id FK → wedding(wedding_id) |
| | 164 | ) |
| | 165 | |
| | 166 | == Table: band |
| | 167 | Represents music bands available for weddings. |
| | 168 | |
| | 169 | band( |
| | 170 | band_id PK, |
| | 171 | band_name, |
| | 172 | genre, |
| | 173 | equipment, |
| | 174 | phone_number, |
| | 175 | price_per_hour |
| | 176 | ) |
| | 177 | |
| | 178 | == Table: band_booking |
| | 179 | Represents band reservations for weddings. |
| | 180 | |
| | 181 | band_booking( |
| | 182 | booking_id PK, |
| | 183 | date, |
| | 184 | start_time, |
| | 185 | end_time, |
| | 186 | status, |
| | 187 | band_id FK → band(band_id), |
| | 188 | wedding_id FK → wedding(wedding_id) |
| | 189 | ) |
| | 190 | |
| | 191 | == Table: registrar |
| | 192 | Represents civil registrars who can officiate weddings. |
| | 193 | |
| | 194 | registrar( |
| | 195 | registrar_id PK, |
| | 196 | name, |
| | 197 | contact, |
| | 198 | location, |
| | 199 | working_hours |
| | 200 | ) |
| | 201 | |
| | 202 | == Table: registrar_booking |
| | 203 | Represents registrar reservations. |
| | 204 | |
| | 205 | registrar_booking( |
| | 206 | booking_id PK, |
| | 207 | date, |
| | 208 | start_time, |
| | 209 | end_time, |
| | 210 | status, |
| | 211 | registrar_id FK → registrar(registrar_id) |
| | 212 | ) |
| | 213 | |
| | 214 | == Integrity Constraints |
| | 215 | |
| | 216 | * Primary keys uniquely identify each table row. |
| | 217 | * Foreign keys enforce referential integrity between related tables. |
| | 218 | * UNIQUE constraints prevent duplicate RSVP and attendance records. |
| | 219 | * CHECK constraints ensure valid time intervals (end_time > start_time). |
| | 220 | * Cascading rules ensure consistent updates and deletions. |
| | 221 | |
| | 222 | == Mapping from ER Model |
| | 223 | Each entity in the ER model is mapped to a table. |
| | 224 | Many-to-many relationships are resolved using associative tables (event_rsvp, attendance, venue_booking, band_booking, photographer_booking). |
| | 225 | All booking entities are associated directly with wedding, reflecting the final ER model design. |
| | 226 | |
| | 227 | == Relational Design History |
| | 228 | |
| | 229 | v0.1 – Initial relational schema |
| | 230 | v0.2 – Alignment with updated ER model |
| | 231 | v0.3 – Removed incorrect event-level reservations |
| | 232 | v0.4 – Refined constraints and keys |
| | 233 | v0.5 – Final relational design aligned with ER Model Version 5 |