Oracle
 sql >> база данни >  >> RDS >> Oracle

Как да изпълним тригер и процедура в oracle

Както вече беше предложено, първо се опитайте да направите дизайна правилен по отношение на вашите изисквания. Можете да приложите много ограничения само като проектирате правилно схемата на вашата база данни.

Стойте далеч от тригери и 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;

Някои от идеите тук:

  1. Цените се съхраняват в отделна таблица, препращат към продукта и имат валидност, така че цената на продукта да може да се променя с времето. Ценовият изглед има ValidTo добавена колона, за да е по-лесно да се работи с нея
  2. Има уникален индекс на цените, така че не можем да имаме 2 цени за един и същ продукт едновременно
  3. Можете да имате много артикули в ред, затова има Orders и OrderLines таблици във връзка 1 към много
  4. В Order_V показва се общата платена сума (с помощта на подзаявка за Payments ) и се показват общите стойности на поръчката (с помощта на подзаявка на OrderLines и Prices , датата на поръчката се използва за получаване на цените от правилния период)

На базата на схемата ще видите кои неща можете да изобразите и кои не. Ваша работа е да го направите да отговаря на вашите изисквания :)

И сега стигнах до момента, в който казвате, че тригерите и процедурите са задължителни във вашия проект. Ето защо имам предложение:

  1. Създайте процедура, която ще позволи на потребителите да създават нова цена за продукт. Определено трябва да провери дали валидността не започва в миналото. След това внедрете друг, който позволява промяна на валидния до момента (също не може да завърши в миналото). След това можете да отмените всички привилегии за вмъкване/актуализиране на таблицата с продукти и да принудите потребителите да използват вашите процедури, които ще съдържат тази бизнес логика.
  2. Създайте таблица PricesLog и задействайте върху Prices който ще вмъкне PriceId, old.Price, new.Price, sysdate и User към регистрационния файл за всички вмъквания/актуализации на таблицата с цените.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle - извлича времево клеймо от низ varchar?

  2. Външно съединение на Oracle с условие за филтър на втората таблица

  3. Как да получите индекс от различна категория, върнат по поръчка от sql в oracle?

  4. Как да видите съдържанието на Check Constraint на Oracle

  5. Отмяна на промените в базата данни с помощта на неявни точки за запис? - Оракул