= Нормализација = == Вовед == Целта на оваа анализа е да се прикаже процесот на нормализација за предложениот модел на базата на податоци Stock Master, од идентификација на функционалните зависиности до постигнување на BCNF (Boyce-Codd нормална форма). Анализата е изведена врз основа на ентитетите и релациите од ER моделот разработен во Фаза P2. 1.'''Академска валидност:''' Нормализација базирана на ентитети е стандардниот пристап за ER-to-релационо мапирање (Elmasri & Navathe, "Fundamentals of Database Systems") '''Заклучок:''' Ги нормализираме секоја релација на ентитет независно, потоа верификуваме релации преку ограничувања на надворешни клучеви. Користиме '''Пристап (Базиран на ентитети)''' затоа што: 2. '''Независни ентитети:''' Нашиот ER модел содржи ентитети кои претставуваат фундаментално различни бизнис концепти: - Sale (трансакциски настан) - !PurchaseOrder (различен трансакциски настан) - Product (инвентарна ставка) - User, Customer, Supplier (луѓе/организации) 3. '''Нема природно комбинирачко настан:''' Не постои еден реален настан каде што сите ентитети учествуваат истовремено: - Sale НЕ има !PurchaseOrder - !PurchaseOrder НЕ има Sale - Product може да постои без било кој од нив == Дел 1: Нормализација базирана на ентитети == === Ентитет 1: USER === ==== Почетна релациска шема ==== '''User'''(userId, username, password, full_name, email, role, is_active) ==== Функционални зависиности ==== '''FD1:''' userId → username, password, full_name, email, role, is_active '''Образложение:''' userId уникатно идентификува корисник, и сите други атрибути опишуваат својства на тој конкретен корисник. ==== Анализа на кандидатски клучеви ==== '''Чекор 1: Идентификуваме атрибути што никогаш не се на десната страна на FDs''' - userId: се појавува само на левата страна '''Чекор 2: Пресметуваме затвореност''' {userId}⁺ = {userId, username, password, full_name, email, role, is_active} Сите атрибути се детерминирани '''Чекор 3: Тестираме минималност''' - Само еден атрибут во клучот, автоматски минимален '''Кандидатски клучеви:''' {userId} '''Примарен клуч:''' userId ==== Чекори на нормализација ==== '''1NF проверка:''' - Сите атрибути атомарни (нема повеќе-вредносни или композитни атрибути) - Примарен клуч дефиниран - Нема повторувачки групи '''Заклучок: User е во 1NF''' '''2NF проверка:''' - Примарниот клуч е еден атрибут - Парцијални зависиности невозможни со еден-атрибутски клуч - Автоматски во 2NF '''Заклучок: User е во 2NF''' '''3NF проверка:''' - Тест за транзитивни зависиности (непримарен → непримарен): - username → password? НЕ (корисничките имиња не детерминираат лозинки) - username → full_name? НЕ (корисничките имиња не идентификуваат луѓе уникатно) - username → email? НЕ - email → username? НЕ (email-овите не детерминираат кориснички имиња) - role → (било кој друг атрибут)? НЕ (role е категорија, не детерминант) - Не постојат транзитивни зависиности '''Заклучок: User е во 3NF''' '''BCNF проверка:''' - За секоја FD X → Y, дали X е суперклуч? - FD1: userId → {...} - Дали userId е суперклуч? ДА (тој е кандидатскиот клуч) '''Заклучок: User е во BCNF''' ==== Финална шема ==== '''User'''(userId, username, password, full_name, email, role, is_active) - '''PK:''' userId - '''Нормална форма:''' BCNF === Ентитет 2: CUSTOMER === ==== Почетна релациска шема ==== '''Customer'''(customerId, name, email, phone, address) ==== Функционални зависиности ==== '''FD2:''' customerId → name, email, phone, address '''Образложение:''' customerId уникатно идентификува клиент, и сите други атрибути опишуваат својства на тој конкретен клиент. ==== Анализа на кандидатски клучеви ==== {customerId}⁺ = {customerId, name, email, phone, address} '''Кандидатски клучеви:''' {customerId} '''Примарен клуч:''' customerId ==== Чекори на нормализација ==== '''1NF:''' Атомарни атрибути '''2NF:''' Еден-атрибутски клуч '''3NF проверка:''' - Не постојат транзитивни зависиности '''BCNF проверка:''' - FD2: customerId е суперклуч ==== Финална шема ==== '''Customer'''(customerId, name, email, phone, address) - '''PK:''' customerId - '''Нормална форма:''' BCNF === Ентитет 3: CATEGORY === ==== Почетна релациска шема ==== '''Category'''(categoryId, name, description) ==== Функционални зависиности ==== '''FD3:''' categoryId → name, description ==== Анализа на кандидатски клучеви ==== {categoryId}⁺ = {categoryId, name, description} '''Кандидатски клучеви:''' {categoryId} '''Примарен клуч:''' categoryId ==== Финална шема ==== '''Category'''(categoryId, name, description) - '''PK:''' categoryId - '''Нормална форма:''' BCNF === Ентитет 4: SUPPLIER === ==== Почетна релациска шема ==== '''Supplier'''(supplierId, name, contact_person, phone, email, address) ==== Функционални зависиности ==== '''FD4:''' supplierId → name, contact_person, phone, email, address ==== Анализа на кандидатски клучеви ==== {supplierId}⁺ = {supplierId, name, contact_person, phone, email, address} '''Кандидатски клучеви:''' {supplierId} '''Примарен клуч:''' supplierId ==== Финална шема ==== '''Supplier'''(supplierId, name, contact_person, phone, email, address) - '''PK:''' supplierId - '''Нормална форма:''' BCNF === Ентитет 5: WAREHOUSE === ==== Почетна релациска шема ==== '''Warehouse'''(warehouseId, name, location, capacity) ==== Функционални зависиности ==== '''FD5:''' warehouseId → name, location, capacity ==== Анализа на кандидатски клучеви ==== {warehouseId}⁺ = {warehouseId, name, location, capacity} '''Кандидатски клучеви:''' {warehouseId} '''Примарен клуч:''' warehouseId ==== Финална шема ==== '''Warehouse'''(warehouseId, name, location, capacity) - '''PK:''' warehouseId - '''Нормална форма:''' BCNF === Ентитет 6: PRODUCT === ==== Почетна релациска шема ==== '''Product'''(productId, name, description, sku, unit_price, reorder_level, categoryId, supplierId) ==== Функционални зависиности ==== '''FD6:''' productId → name, description, sku, unit_price, reorder_level, categoryId, supplierId '''FD7:''' sku → productId, name, description, unit_price, reorder_level, categoryId, supplierId '''Образложение:''' ER моделот специфицира дека '''и productId и sku се уникатни идентификатори''' ==== Анализа на кандидатски клучеви ==== '''Тест productId:''' {productId}⁺ = {productId, name, description, sku, unit_price, reorder_level, categoryId, supplierId} - Сите атрибути детерминирани - Минимален '''Тест sku:''' {sku}⁺ = {sku, productId, name, description, unit_price, reorder_level, categoryId, supplierId} - Сите атрибути детерминирани - Минимален '''Кандидатски клучеви:''' {productId}, {sku} '''Примарен клуч:''' productId '''Алтернативен клуч:''' sku ==== Чекори на нормализација ==== '''3NF проверка:''' '''Важно: Надворешни клучеви vs. Транзитивни зависиности''' Оваа релација содржи '''categoryId''' и '''supplierId''' кои се надворешни клучеви. '''Прашање:''' Дали овие создаваат транзитивни зависиности? '''Одговор:''' НЕ '''Објаснување:''' Надворешните клучеви се '''индикатори на релации''', не транзитивни зависиности. Вистинските зависни атрибути (category_name, supplier_name) се складирани во нивните соодветни релации (Category, Supplier), одржувајќи ја нормализацијата. '''Product е во BCNF''' ==== Финална шема ==== '''Product'''(productId, name, description, sku, unit_price, reorder_level, categoryId, supplierId) - '''PK:''' productId - '''AK:''' sku - '''FK:''' categoryId → Category(categoryId) - '''FK:''' supplierId → Supplier(supplierId) - '''Нормална форма:''' BCNF === Ентитет 7: SALE === ==== Почетна релациска шема ==== '''Sale'''(saleId, date_time, total_amount, userId, customerId, warehouseId) ==== Функционални зависиности==== '''FD8:''' saleId → date_time, total_amount, userId, customerId, warehouseId ==== Анализа на кандидатски клучеви ==== {saleId}⁺ = {saleId, date_time, total_amount, userId, customerId, warehouseId} '''Кандидатски клучеви:''' {saleId} '''Примарен клуч:''' saleId ==== Финална шема ==== '''Sale'''(saleId, date_time, total_amount, userId, customerId, warehouseId) - '''PK:''' saleId - '''FK:''' userId → User(userId) - '''FK:''' customerId → Customer(customerId) - '''FK:''' warehouseId → Warehouse(warehouseId) - '''Нормална форма:''' BCNF === Ентитет 8: PURCHASEORDER === ==== Почетна релациска шема ==== '''!PurchaseOrder'''(poId, order_date, expected_delivery_date, status, supplierId, warehouseId) ==== Функционални зависиности ==== '''FD9:''' poId → order_date, expected_delivery_date, status, supplierId, warehouseId ==== Анализа на кандидатски клучеви ==== {poId}⁺ = {poId, order_date, expected_delivery_date, status, supplierId, warehouseId} '''Кандидатски клучеви:''' {poId} '''Примарен клуч:''' poId ==== Финална шема ==== '''!PurchaseOrder'''(poId, order_date, expected_delivery_date, status, supplierId, warehouseId) - '''PK:''' poId - '''FK:''' supplierId → Supplier(supplierId) - '''FK:''' warehouseId → Warehouse(warehouseId) - '''Нормална форма:''' BCNF === Ентитет 9: SALEITEM (Слаб ентитет) === ==== Почетна релациска шема ==== '''!SaleItem'''(saleId, productId, quantity, unit_price_at_sale) ==== Функционални зависиности ==== '''FD10:''' (saleId, productId) → quantity, unit_price_at_sale ==== Анализа на кандидатски клучеви ==== '''Тест (saleId, productId):''' {saleId, productId}⁺ = {saleId, productId, quantity, unit_price_at_sale} - Сите атрибути детерминирани - Двата компоненти неопходни '''Кандидатски клучеви:''' {(saleId, productId)} '''Примарен клуч:''' (saleId, productId) ==== Чекори на нормализација ==== '''2NF проверка:''' Нема парцијални зависиности. Двата непримарни атрибути (quantity, unit_price_at_sale) бараат '''ЦЕЛОСЕН композитен клуч''' (saleId, productId) за детерминација. '''!SaleItem е во 2NF''' '''3NF проверка:''' Не постојат транзитивни зависиности '''!SaleItem е во 3NF''' '''BCNF проверка:''' - FD10: (saleId, productId) е суперклуч '''!SaleItem е во BCNF''' ==== Карактеристики на слаб ентитет ==== 1. '''Зависимост од постоење:''' !SaleItem не може да постои без родителска Sale 2. '''Идентификувачка релација:''' Надворешниот клуч (saleId) е дел од примарниот клуч 3. '''Парцијален клуч:''' productId ги разликува различните производи во иста продажба ==== Финална шема ==== '''!SaleItem'''(saleId, productId, quantity, unit_price_at_sale) - '''PK:''' (saleId, productId) - '''FK:''' saleId → Sale(saleId) - '''идентификувачка''' - '''FK:''' productId → Product(productId) - '''Тип на ентитет:''' Слаб ентитет (зависен од Sale) - '''Нормална форма:''' BCNF === Ентитет 10: PURCHASEORDERITEM (Слаб ентитет) === ==== Почетна релациска шема ==== '''!PurchaseOrderItem'''(poId, productId, quantity, unit_cost) ==== Функционални зависиности ==== '''FD11:''' (poId, productId) → quantity, unit_cost ==== Анализа на кандидатски клучеви ==== {poId, productId}⁺ = {poId, productId, quantity, unit_cost} '''Кандидатски клучеви:''' {(poId, productId)} '''Примарен клуч:''' (poId, productId) ==== Финална шема ==== '''!PurchaseOrderItem'''(poId, productId, quantity, unit_cost) - '''PK:''' (poId, productId) - '''FK:''' poId → !PurchaseOrder(poId) - '''идентификувачка''' - '''FK:''' productId → Product(productId) - '''Тип на ентитет:''' Слаб ентитет (зависен од !PurchaseOrder) - '''Нормална форма:''' BCNF === Ентитет 11: WAREHOUSESTOCK (Слаб ентитет) === ==== Почетна релациска шема ==== '''!WarehouseStock'''(warehouseId, productId, quantity_on_hand, last_updated) ==== Функционални зависиности ==== '''FD12:''' (warehouseId, productId) → quantity_on_hand, last_updated ==== Анализа на кандидатски клучеви ==== {warehouseId, productId}⁺ = {warehouseId, productId, quantity_on_hand, last_updated} '''Кандидатски клучеви:''' {(warehouseId, productId)} '''Примарен клуч:''' (warehouseId, productId) ==== Финална шема ==== '''!WarehouseStock'''(warehouseId, productId, quantity_on_hand, last_updated) - '''PK:''' (warehouseId, productId) - '''FK:''' warehouseId → Warehouse(warehouseId) - '''идентификувачка''' - '''FK:''' productId → Product(productId) - '''Тип на ентитет:''' Слаб ентитет (зависен од Warehouse) - '''Нормална форма:''' BCNF == Дел 2: Сеопфатно резиме == === Резиме на функционални зависиности === 1. '''User:''' userId → username, password, full_name, email, role, is_active 2. '''Customer:''' customerId → name, email, phone, address 3. '''Category:''' categoryId → name, description 4. '''Supplier:''' supplierId → name, contact_person, phone, email, address 5. '''Warehouse:''' warehouseId → name, location, capacity 6. '''Product:''' * productId → name, description, sku, unit_price, reorder_level, categoryId, supplierId * sku → productId, name, description, unit_price, reorder_level, categoryId, supplierId 7. '''Sale:''' saleId → date_time, total_amount, userId, customerId, warehouseId 8. '''PurchaseOrder:''' poId → order_date, expected_delivery_date, status, supplierId, warehouseId 9. '''SaleItem:''' (saleId, productId) → quantity, unit_price_at_sale 10. '''PurchaseOrderItem:''' (poId, productId) → quantity, unit_cost 11. '''WarehouseStock:''' (warehouseId, productId) → quantity_on_hand, last_updated === Резиме на кандидатски клучеви === '''User:''' * Кандидатски клуч: {userId} * Примарен клуч: userId '''Customer:''' * Кандидатски клуч: {customerId} * Примарен клуч: customerId '''Category:''' * Кандидатски клуч: {categoryId} * Примарен клуч: categoryId '''Supplier:''' * Кандидатски клуч: {supplierId} * Примарен клуч: supplierId '''Warehouse:''' * Кандидатски клуч: {warehouseId} * Примарен клуч: warehouseId '''Product:''' * Кандидатски клучеви: {productId}, {sku} * Примарен клуч: productId * Алтернативен клуч: sku '''Sale:''' * Кандидатски клуч: {saleId} * Примарен клуч: saleId '''PurchaseOrder:''' * Кандидатски клуч: {poId} * Примарен клуч: poId '''SaleItem:''' * Кандидатски клуч: {(saleId, productId)} * Примарен клуч: (saleId, productId) '''PurchaseOrderItem:''' * Кандидатски клуч: {(poId, productId)} * Примарен клуч: (poId, productId) '''WarehouseStock:''' * Кандидатски клуч: {(warehouseId, productId)} * Примарен клуч: (warehouseId, productId) == Заклучок == Анализата покажа дека релациската шема од Фаза P2 веќе е во BCNF без потреба од дополнителни измени. '''Резултати од анализата:''' * Сите 11 релации се во BCNF * Не е потребна декомпозиција * Не е потребна реорганизација * Релациската шема од Фаза P2 може директно да се имплементира.