जैसा कि पहले से ही प्रस्तावित है, पहले अपनी आवश्यकताओं के संबंध में डिजाइन को सही करने का प्रयास करें। आप केवल अपने डेटाबेस स्कीमा को सही ढंग से डिज़ाइन करके कई बाधाओं को लागू कर सकते हैं।
जितना हो सके ट्रिगर्स और PL/SQL से दूर रहें। यह आपको अंत में बेहतर डिजाइन के लिए मजबूर करेगा और भुगतान करेगा।
व्यावसायिक तर्क के लिए ट्रिगर्स का उपयोग करने से पहले, उन चीज़ों के लिए दृश्यों का उपयोग करने का प्रयास करें जिन्हें चुना जा सकता है। डेटाबेस के लिए यही है।
जब आप "पूर्ण" हो जाते हैं, तो प्रदर्शन के लिए परीक्षण करें और यदि यह उप-इष्टतम है, तो अपनी स्कीमा में सुधार करें। अगर कुछ भी मदद नहीं करता है, तो व्यावसायिक तर्क के लिए ट्रिगर का उपयोग करना शुरू करें।
मैंने एक नमूना एक साथ रखा है विचारों के साथ मैं बात कर रहा हूँ। मुझे आशा है कि यह आपको आरंभ कर सकता है।
create table Products (
ProdId number generated always as identity primary key
, ProdName varchar2(20) not null
);
create table Stores (
StoreId number generated always as identity primary key
, StoreName varchar2(20) not null
);
create table Customers (
CustomerId number generated always as identity primary key
, CustomerName varchar2(20) not null
);
create table Prices (
PriceId number generated always as identity primary key
, ProdId number not null
, Price number
, ValidFrom date default on null sysdate
, constraint fk_Prices_Product foreign key (ProdId) references Products (ProdId)
);
create unique index uniq_prices_product_price on Prices (ProdId, ValidFrom);
create table Orders (
OrderId number generated always as identity primary key
, CustomerId number not null
, StoreId number not null
, OrderedAt date default on null sysdate
, constraint fk_Orders_Customer foreign key (CustomerId) references Customers (CustomerId)
, constraint fk_Orders_Store foreign key (StoreId) references Stores (StoreId)
);
create table OrderLines (
OrderLineId number generated always as identity primary key
, OrderId number not null
, ProdId number not null
, ProdQuantity number not null
, constraint fk_OrderLines_Order foreign key (OrderId) references Orders (OrderId)
, constraint fk_OrderLines_Prod foreign key (ProdId) references Products (ProdId)
);
create table Payments (
PaymentId number generated always as identity primary key
, OrderId number not null
, PaidAt date default on null sysdate
, PaidAmount number not null
, constraint fk_Payments_Order foreign key (OrderId) references Orders (OrderId)
);
create view Prices_V as
select
p.*
, coalesce(
lead(p.ValidFrom) over (partition by p.ProdId order by p.ValidFrom)
, to_date('9999', 'YYYY')
) ValidTo
from Prices p;
create view Orders_V as
select
o.*
, (
select sum(ol.ProdQuantity * p.Price)
from OrderLines ol
join Prices_V p on (p.ProdId = ol.ProdId and o.OrderedAt between p.ValidFrom and p.ValidTo)
where o.OrderId = ol.OrderId
) Total
, (
select sum(PaidAmount)
from Payments p
where p.OrderId = o.OrderId
) TotalPaid
from Orders o;
insert into Products(ProdName)
select 'Prod A' from dual union all
select 'Prod B' from dual;
insert into Stores(StoreName) values ('Store A');
insert into Customers(CustomerName)
select 'Customer A' from dual union all
select 'Customer B' from dual;
insert into Prices(ProdId, Price, ValidFrom)
select 1, 10, sysdate - 10 from dual union all
select 1, 12, sysdate - 2 from dual union all
select 1, 14, sysdate + 3 from dual union all
select 2, 100, sysdate - 10 from dual union all
select 2, 90, sysdate - 2 from dual union all
select 2, null, sysdate + 5 from dual;
insert into Orders(CustomerId, StoreId, OrderedAt)
select 1 cid, 1 stoid, sysdate - 5 from dual union all
select 2, 1, sysdate - 5 from dual union all
select 2, 1, sysdate - 1 from dual;
insert into OrderLines(OrderId, ProdId, ProdQuantity)
select 1 ordid, 1 prodid, 3 prodquant from dual union all
select 1, 2, 2 from dual union all
select 2, 2, 10 from dual union all
select 3, 2, 10 from dual;
insert into Payments(OrderId, PaidAmount) values (2, 500);
select * from Prices_V order by ProdId, ValidFrom;
select * from OrderLines order by OrderId, ProdId;
select * from Orders_v order by OrderId;
वहां के कुछ विचार:
- कीमतें अलग टेबल में स्टोर की जाती हैं, उत्पाद को संदर्भित करती हैं और वैधता रखती हैं ताकि उत्पाद की कीमत समय के साथ बदल सके। मूल्य दृश्य में
ValidTo
. है कॉलम जोड़ा गया ताकि इसके साथ काम करना आसान हो - कीमतों पर एक अद्वितीय अनुक्रमणिका है ताकि हमारे पास एक ही समय में एक ही उत्पाद के लिए 2 मूल्य नहीं हो सकते हैं
- आपके पास क्रम में कई आइटम हो सकते हैं, इसलिए
Orders
. है औरOrderLines
1-से-अनेक संबंध में तालिकाएं Order_V
में कुल भुगतान दिखाया गया है (Payments
. पर एक सबक्वेरी का उपयोग करके) ) और कुल ऑर्डर मान दिखाया गया है (OrderLines
. पर एक सबक्वेरी का उपयोग करके) औरPrices
, ऑर्डर की तारीख का उपयोग कीमतों को सही अवधि के रूप में प्राप्त करने के लिए किया जाता है)
स्कीमा के आधार पर आप देखेंगे कि आप किन चीजों का प्रतिनिधित्व कर सकते हैं और किन चीजों का आप नहीं कर सकते। इसे अपनी आवश्यकताओं के अनुरूप बनाना आपका काम है :)
और अब मैं उस बिंदु पर आ गया हूं जो आप कहते हैं कि आपके प्रोजेक्ट में ट्रिगर्स और प्रक्रियाएं अनिवार्य हैं। इसलिए मेरे पास एक प्रस्ताव है:
- एक ऐसी प्रक्रिया बनाएं जिससे उपयोगकर्ता किसी उत्पाद के लिए नई कीमत तैयार कर सकें। यह निश्चित रूप से जांचना चाहिए कि वैधता अतीत में शुरू नहीं होती है। फिर एक और लागू करें जो वैध तिथि को बदलने की अनुमति देता है (अतीत में भी समाप्त नहीं हो सकता)। आप उत्पाद तालिका पर किसी भी सम्मिलित/अद्यतन विशेषाधिकार को रद्द कर सकते हैं और उपयोगकर्ताओं को अपनी प्रक्रियाओं का उपयोग करने के लिए मजबूर कर सकते हैं जिसमें यह व्यावसायिक तर्क शामिल होगा।
- एक टेबल बनाएं
PricesLog
औरPrices
. पर ट्रिगर करें जो PriceId, old.Price, new.Price, sysdate औरUser
प्रविष्ट करेगा मूल्य तालिका में किसी भी प्रविष्टि/अपडेट पर लॉग ऑन करने के लिए।