sql >> Databáze >  >> RDS >> Oracle

Jak spustit trigger a proceduru v oracle

Jak již bylo navrženo, nejprve se pokuste získat správný design s ohledem na vaše požadavky. Pouhým správným návrhem databázového schématu můžete implementovat mnoho omezení.

Držte se od triggerů a PL/SQL co nejdéle. Donutí vás to nakonec k lepšímu designu a vyplatí se to.

Před použitím spouštěčů pro obchodní logiku zkuste použít zobrazení pro věci, které lze vybrat. K tomu slouží databáze.

Až budete "hotoví", otestujte výkon a pokud není optimální, vylepšete své schéma. Pokud nic nepomůže, začněte používat spouštěče pro obchodní logiku.

Dal jsem dohromady ukázku s názory, o kterých mluvím. Doufám, že vám to pomůže začít.

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;

Některé z nápadů:

  1. Ceny jsou uloženy v samostatné tabulce, odkazují na produkt a mají platnost, takže se cena produktu může v průběhu času měnit. Zobrazení ceny má ValidTo sloupec přidán, takže je snazší s ním pracovat
  2. Existuje jedinečný index cen, takže nemůžeme mít 2 ceny pro stejný produkt ve stejnou dobu
  3. Můžete mít mnoho položek v pořadí, takže proto existují Orders a OrderLines tabulky ve vztahu 1-to-many
  4. V Order_V zobrazí se celková zaplacená částka (pomocí dílčího dotazu na Payments ) a zobrazí se celkové hodnoty objednávky (pomocí dílčího dotazu na OrderLines a Prices , datum objednávky se používá k získání cen ze správného období)

Na základě schématu uvidíte, jaké věci můžete reprezentovat a které ne. Je vaším úkolem, aby to odpovídalo vašim požadavkům :)

A teď jsem se dostal k bodu, kdy říkáte, že spouštěče a procedury jsou ve vašem projektu povinné. Proto mám návrh:

  1. Vytvořte postup, který uživatelům umožní vytvořit novou cenu produktu. Rozhodně by měl kontrolovat, že platnost nezačíná v minulosti. Pak implementujte jiný, který umožňuje změnu platného k datu (také nemůže končit v minulosti). Poté můžete zrušit veškerá oprávnění pro vkládání/aktualizaci v tabulce Produkty a přimět uživatele, aby používali vaše postupy, které budou obsahovat tuto obchodní logiku.
  2. Vytvořte tabulku PricesLog a spustit na Prices který vloží PriceId, old.Price, new.Price, sysdate a User do protokolu o všech přílohách/aktualizacích tabulky cen.



  1. Jak odstranit sloupec v tabulce

  2. Jak provádět průběžné upgrady pro MySQL

  3. WAMP Nelze přistupovat k místní síti 403 Zakázáno

  4. MySQL:VYBERTE UNIKÁTNÍ HODNOTU