Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Jak wykonać wyzwalacz i procedurę w Oracle?

Jak już zaproponowano, najpierw postaraj się, aby projekt był zgodny z Twoimi wymaganiami. Możesz zaimplementować wiele ograniczeń, projektując poprawnie schemat bazy danych.

Trzymaj się z dala od wyzwalaczy i PL/SQL tak długo, jak to możliwe. W końcu zmusi cię to do lepszego projektowania i opłaci się.

Przed użyciem wyzwalaczy logiki biznesowej spróbuj użyć widoków dla rzeczy, które można wybrać. Do tego służy baza danych.

Kiedy skończysz, przetestuj wydajność i jeśli jest nieoptymalna, popraw swój schemat. Jeśli nic nie pomoże, zacznij używać wyzwalaczy logiki biznesowej.

Stworzyłem próbkę z widokami, o których mówię. Mam nadzieję, że to pomoże Ci zacząć.

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;

Niektóre z pomysłów tam:

  1. Ceny są przechowywane w oddzielnej tabeli, odnoszą się do produktu i mają ważność, dzięki czemu cena produktu może się zmieniać w czasie. Widok ceny ma ValidTo dodano kolumnę, aby ułatwić pracę
  2. Istnieje unikalny indeks cen, więc nie możemy mieć 2 cen tego samego produktu w tym samym czasie
  3. Możesz mieć wiele pozycji w kolejności, dlatego istnieje Orders i OrderLines tabele w relacji 1-do-wielu
  4. W Order_V pokazana jest suma zapłacona (za pomocą podzapytania w Payments ) i pokazane są całkowite wartości zamówienia (przy użyciu podzapytania w OrderLines i Prices , data zamówienia jest używana do uzyskania cen z właściwego okresu)

Na podstawie schematu zobaczysz, jakie rzeczy możesz reprezentować, a których nie. Twoim zadaniem jest dostosowanie go do Twoich wymagań :)

A teraz doszedłem do punktu, w którym mówisz, że wyzwalacze i procedury są obowiązkowe w twoim projekcie. Dlatego mam propozycję:

  1. Utwórz procedurę, która umożliwi użytkownikom tworzenie nowej ceny produktu. Należy zdecydowanie sprawdzić, czy ważność nie zaczyna się w przeszłości. Następnie zaimplementuj inną, która pozwala na zmianę aktualnej daty ważności (również nie może kończyć się w przeszłości). Możesz wtedy cofnąć wszelkie uprawnienia wstawiania/aktualizacji w tabeli Produkty i zmusić użytkowników do korzystania z procedur, które będą zawierać tę logikę biznesową.
  2. Utwórz tabelę PricesLog i uruchom na Prices który wstawi PriceId, old.Price, new.Price, sysdate i User do logu na wszelkie wstawki/aktualizacje do tabeli cen.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. obsługa wielu baz danych dla tych samych klas JPA

  2. podzapytanie - uzyskanie najwyższego wyniku

  3. Wywoływanie funkcji SQL Oracle PL z Excela VBA

  4. Opinie na temat uwierzytelniania między warstwami aplikacji i bazy danych

  5. Oracle PLS-00363:wyrażenie „” nie może być użyte jako cel przypisania