Обновление записи в нескольких таблицах с расчетом (общий счет) с использованием сценария Oracle SQL - PullRequest
3 голосов
/ 23 ноября 2011

У меня есть таблица SERVICE, которая хранит суммы за услуги в одной таблице, а затем ссылается на таблицу LINE, которая подключается к INVOICE.

Я хочу создать триггер, который обновляет итоговое значение на строку на основе суммы в таблице SERVICE и, наконец, промежуточного итога для счета в таблице INVOICE.

Я застрял в команде UPDATE, чтобы получить 20.00 для обновления в таблицу LINE и таблицу SERVICE.

Как я могу создать это UPDATE?

CREATE TABLE SERVICE   
(    
ServiceID       char(6)         NOT NULL,    
Description varchar(50)     NOT NULL,    
Price           decimal(6,2)    NOT NULL,    
CONSTRAINT PK_ServiceID PRIMARY KEY (ServiceID)   
);

CREATE TABLE INVOICE    
(    
InvoiceID       char(6)     NOT NULL,    
InvoiceTotal    LONG,    
CustomerID      char(6)     NOT NULL,    
EmployeeID      char(6)     NOT NULL,    
InvoiceDate date NOT NULL,    
Notes         varchar(200),    
CONSTRAINT PK_Invoice PRIMARY KEY (InvoiceID),    
CONSTRAINT FK_CUSTOMER FOREIGN KEY (CustomerID) REFERENCES CUSTOMER(CustomerID),    
CONSTRAINT FK_EMPLOYEE FOREIGN KEY (EmployeeID) REFERENCES EMPLOYEE(EmployeeID)    
);

CREATE TABLE LINE    (    
LineID    char(6) NOT NULL,    
LineQty  int     NOT NULL,    
LinePrice decimal(6,2),    
InvoiceID char(6) NOT NULL,    
ServiceID char(6) NOT NULL,    
CONSTRAINT  PK_LineID PRIMARY KEY (LineID),    
CONSTRAINT  FK_INVOICE  FOREIGN KEY (InvoiceID) REFERENCES INVOICE(InvoiceID),    
CONSTRAINT  FK_SERVICE  FOREIGN KEY (ServiceID) REFERENCES SERVICE(ServiceID)    
);

INSERT INTO SERVICE(ServiceID, Description, Price)    
VALUES('SE0001', 'Press Shirt', 20.00);

INSERT INTO SERVICE(ServiceID, Description, Price)    
VALUES('SE0002', 'Press Slacks', 15.00);

INSERT INTO INVOICE(InvoiceID, CustomerID, EmployeeID, InvoiceDate)    
VALUES('IN0001', 'CU0001', 'EE0001', '01-SEP-2011');

INSERT INTO LINE(LineID, LineQty, InvoiceID, ServiceID)    
VALUES('LI0001', '2', 'IN0001', 'SE0001');

1 Ответ

3 голосов
/ 23 ноября 2011

Как правило, мне было бы немного не по себе от вычисляемых столбцов в таблице, таких как строка или счет-фактура.Часто возникают проблемы с целостностью данных, когда вычисляемый результат не равен сохраненному результату.

Вместо того, чтобы иметь столбец LINE.LinePrice, у вас может быть запрос, который вычислит LinePrice по требованию:

    SELECT l.LineID, l.LineQty, l.LineQty * s.Price AS LinePrice, l.InvoiceID, l.ServiceID
      FROM LINE l, SERVICE s
      WHERE s.ServiceID = l.ServiceID

Как и в случае с INVOICE.InvoiceTotal, вы можете сделать запрос примерно так:

    SELECT i.InvoiceID, SUM(x.LinePrice) AS InvoiceTotal
      FROM INVOICE i
          ,(SELECT l.InvoiceID, l.LineQty * s.Price AS LinePrice
              FROM LINE l, SERVICE s
              WHERE s.ServiceID = l.ServiceID) x
      WHERE i.InvoiceID = x.InvoiceID
      GROUP BY i.InvoiceID

Если вы пойдете по этому маршруту, то вам также придется подумать о том, что происходит, когда цена услуги меняется,Если вы печатаете старые счета-фактуры, собираетесь ли вы рассчитывать новые итоги или вы хотите использовать исторические значения для вычисления того, каким был счет-фактура в прошлом?Вероятно, последнее, поэтому изменения в таблице Service должны быть эффективными с датой, имеющей дату как часть ключа.Затем вы можете отслеживать исторические цены.

Но я также понимаю, что нужно иметь фиксированное статическое значение, если счет выставлен (обычно это архивный документ).Если вы хотите пройти маршрут триггера, триггер может выглядеть примерно так (у меня нет доступного экземпляра Oracle, поэтому вам нужно будет проверить синтаксис):

    CREATE OR REPLACE TRIGGER line_insert
    BEFORE INSERT ON line
    FOR EACH ROW
    BEGIN
        SELECT :new.LineQty * Price
          INTO :new.LinePrice
          FROM Service
          WHERE serviceID = :new.ServiceID;
    END;

Это просто попыткасделайте LinePrice на Вставке.Вам также необходимо увеличить InvoiceTotal.И вам нужно будет следить за сценариями UPDATE (вычесть: старая сумма и добавить: новая сумма) и DELETE (вычесть: старая сумма).

...