Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Wie man Trigger und Prozedur in Oracle ausführt

Wie bereits vorgeschlagen, versuchen Sie zunächst, das Design in Bezug auf Ihre Anforderungen richtig zu machen. Sie können viele Einschränkungen implementieren, indem Sie einfach Ihr Datenbankschema richtig entwerfen.

Halten Sie sich so lange wie möglich von Triggern und PL/SQL fern. Es wird Sie am Ende zu einem besseren Design zwingen und sich auszahlen.

Bevor Sie Trigger für die Geschäftslogik verwenden, versuchen Sie, Ansichten für Dinge zu verwenden, die ausgewählt werden können. Dafür ist die Datenbank da.

Wenn Sie „fertig“ sind, testen Sie die Leistung und verbessern Sie Ihr Schema, wenn sie suboptimal ist. Wenn nichts hilft, verwenden Sie Trigger für die Geschäftslogik.

Ich habe ein Beispiel zusammengestellt mit Ansichten spreche ich. Ich hoffe, es kann Ihnen den Einstieg erleichtern.

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;

Einige der darin enthaltenen Ideen:

  1. Preise werden in einer separaten Tabelle gespeichert, beziehen sich auf das Produkt und haben Gültigkeit, sodass sich der Produktpreis im Laufe der Zeit ändern kann. Preisansichten haben ValidTo Spalte hinzugefügt, damit es einfacher ist, damit zu arbeiten
  2. Es gibt einen einzigartigen Preisindex, sodass wir nicht 2 Preise für dasselbe Produkt gleichzeitig haben können
  3. Sie können viele Artikel geordnet haben, deshalb gibt es Orders und OrderLines Tabellen in 1:n-Beziehung
  4. In Order_V der bezahlte Gesamtbetrag wird angezeigt (unter Verwendung einer Unterabfrage zu Payments). ) und die Gesamtbestellwerte werden angezeigt (unter Verwendung einer Unterabfrage auf OrderLines und Prices , Datum der Bestellung wird verwendet, um Preise aus dem richtigen Zeitraum zu erhalten)

Anhand des Schemas sehen Sie, was Sie darstellen können und was nicht. Es ist Ihre Aufgabe, es Ihren Anforderungen anzupassen :)

Und jetzt bin ich an dem Punkt angelangt, an dem Sie sagen, dass Trigger und Verfahren in Ihrem Projekt obligatorisch sind. Daher habe ich einen Vorschlag:

  1. Erstellen Sie ein Verfahren, mit dem Benutzer einen neuen Preis für ein Produkt erstellen können. Es sollte unbedingt geprüft werden, dass die Gültigkeit nicht in der Vergangenheit beginnt. Implementieren Sie dann eine andere, die das Ändern des Gültig-bis-Datums ermöglicht (kann auch nicht in der Vergangenheit enden). Sie können dann alle Einfüge-/Aktualisierungsberechtigungen für die Produkttabelle widerrufen und Benutzer zwingen, Ihre Prozeduren zu verwenden, die diese Geschäftslogik enthalten.
  2. Erstellen Sie eine Tabelle PricesLog und auf Prices auslösen Dadurch werden PriceId, old.Price, new.Price, sysdate und User eingefügt zum Anmelden eventueller Einfügungen/Aktualisierungen der Preistabelle.