2015-09-23 3 views
3

Я пытаюсь создать триггер для поддельной базы данных. Предположим, что - это производный атрибут с именем «total_loan» для БАНКОВСКОГО ФИЛИАЛА, который используется для поддержания общей суммы кредита в каждом филиале. Я пытаюсь создать триггер, чтобы поддерживать этот производный атрибут. Мой триггер, таким образом, кажется, чтобы остановить мой load.sql сценарий показано ниже:Создание простого триггера Oracle SQl

CREATE TABLE a2_bankbranch (
name   VARCHAR(200) NOT NULL, 
branch_num  VARCHAR(200) NOT NULL, 
address  VARCHAR(200) NOT NULL, 
routing_code VARCHAR(200) NOT NULL, 
total_loan  NUMBER(38), 
FOREIGN KEY(routing_code) REFERENCES a2_bank(routingcode), 
PRIMARY KEY(branch_num, routing_code) 
); 
@trig.sql 

INSERT INTO a2_bankbranch VALUES 
('ASB', '5', '3 gladstone rd', '123456', ''); 
INSERT INTO a2_bankbranch VALUES 
('ASB', '4', '28 stevee rd', '123456', ''); 

CREATE TABLE a2_loan (
loan_num  CHAR(10) PRIMARY KEY, 
type   VARCHAR(200) NOT NULL, 
amount   NUMBER(38) NOT NULL, 
contract_date DATE   NOT NULL, 
branch_num  VARCHAR(200) NOT NULL, 
routing_code VARCHAR(200) NOT NULL, 
FOREIGN KEY(routing_code) REFERENCES a2_bank(routing_code), 
Foreign KEY(branch_num) REFERENCES a2_bankbranch(branch_num) 
); 

INSERT INTO a2_loan VALUES 
('323', 'Mortgage', '2000000', TO_DATE('11-03-1994', 'DD-MM-YYYY'), '5', '123456'); 
INSERT INTO a2_loan VALUES 
('33', 'Car', '2000', TO_DATE('12-08-1994', 'DD-MM-YYYY'), '5', '123456'); 
INSERT INTO a2_loan VALUES 
('3243', 'Pesonal', '875', TO_DATE('14-06-1994', 'DD-MM-YYYY'), '5', '123456'); 
INSERT INTO a2_loan VALUES 
('6', 'Mortgage', '400500', TO_DATE('11-06-1994', 'DD-MM-YYYY'), '5', '123456'); 

Мой триггер будет показано ниже, начальная вставка не работает, и я не уверен, что положить в моих WHERE и SET строки для обновления и удаление trig.sql показан ниже

-- Create a trigger that will update the total loan amount 
--that each bank brach may have 

CREATE OR REPLACE TRIGGER ttl 
AFTER INSERT OR UPDATE OR DELETE OF total_loan ON a2-bankbranch 
FOR EACH ROW 
BEGIN 
IF INSERTING THEN 
UPDATE a2_loan 
SET total_loan = total_loan + :NEW.amount 
WHERE branch_num = :NEW.bank_num; 
ELSIF UPDATING THEN 
UPDATE a2_loan 
SET total_loan = total_loan + amount 
WHERE 
ELSE --deleting 
UPDATE a2_loan 
WHERE 
END; 

Любая помощь будет высоко оценили

+0

Вы помечено это для SQL Server и Oracle, двумя различными базами данных. Какой из них вы используете? Я предполагаю, что Oracle. Я предполагаю, что тег SQL Server должен быть удален. Ваши типы данных не имеют смысла - вы сохраняете числовые значения в столбцах 'varchar2'. Я ожидаю, что вы хотите, чтобы триггер был определен на таблице «кредит», но нет очевидного способа связать кредит с филиалом в вашей модели данных. –

+0

Да, извините, используя Oracle. Как вы можете видеть, я немного потерян, конечным результатом триггера должно быть то, что если я изменю сумму кредита, которую конкретный клиент имеет, база данных автоматически обновит общую сумму кредита, выданную банком-банком, что клиент является член в. Это помогает? – Val

+0

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

ответ

0

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

Это, как говорится, я надеюсь, что вы хотите что-то вроде

CREATE OR REPLACE TRIGGER your_trigger_name 
    AFTER INSERT, UPDATE, DELETE ON a2_loan 
    FOR EACH ROW 
BEGIN 
    IF INSERTING 
    THEN 
    UPDATE a2_bankbranch 
     SET total_loan = nvl(total_loan,0) + :new.amount 
    WHERE routing_code = :new.routing_code 
     AND branch_num = :new.branch_num; 
    END IF; 

    IF UPDATING 
    THEN 
    UPDATE a2_bankbranch 
     SET total_loan = nvl(total_loan,0) - :old.amount 
    WHERE routing_code = :old.routing_code 
     AND branch_num = :old.branch_num; 

    UPDATE a2_bankbranch 
     SET total_loan = nvl(total_loan,0) + :new.amount 
    WHERE routing_code = :new.routing_code 
     AND branch_num = :new.branch_num; 
    END IF; 

    IF DELETING 
    THEN 
    UPDATE a2_bankbranch 
     SET total_loan = nvl(total_loan,0) - :old.amount 
    WHERE routing_code = :old.routing_code 
     AND branch_num = :old.branch_num; 
    END IF; 
END; 
+0

Просто для того, чтобы усилить, почему вы не используете триггеры: Салли вносит кредит в 5 долларов. Триггер устанавливает общий объем кредитов филиалу от 100 до 105 долларов США. Прежде чем Салли зафиксирует свою вставку (делая ее видимой для других пользователей), Дженни вносит кредит в 10 долларов. Триггер Дженни (который не может видеть кредит Салли) устанавливает общие отраслевые кредиты от 100 до 110 долларов США. Дженни совершает. Общая сумма отделения составляет 110 долларов США. Спустя несколько мгновений Салли совершает. Сумма отделения составит 105 долларов США. Фактическая сумма кредитов, включая как Sally's, так и Jenny's, составляет 115 долларов США. – KevinKirkpatrick

+0

@KevinKirkpatrick - Это было бы проблемой с некоторыми потенциальными реализациями такого рода триггеров. Это не будет проблемой с этим конкретным триггером, потому что два сеанса не могут заблокировать одну и ту же строку, чтобы обновлять ее одновременно. В этой реализации сессия Дженни блокируется до завершения сеанса Салли. Проблема заключалась бы в том, что если бы сессия Салли зависела по какой-либо причине, никто не сможет обрабатывать кредиты для этого филиала до тех пор, пока администратор базы данных не определит и не убьет сессию. Это может быть катастрофическим ограничителем масштабируемости приложения. –

+0

Мы оба немного сбиты: когда Дженни выпускает свою вставку, ее обновление будет заблокировано до тех пор, пока Салли не заберет. Конец Sally обновит общую сумму до 105 долларов США. После совершения сделки Салли сессия Дженни будет разблокирована. Однако он все равно установит общее количество неверно ($ 110, а не $ 115). Для этого есть обходные пути: триггер может сначала выбрать строку ветвления для обновления (ожидая блокировки excl на ней), затем выпустить обновление total_loan = total_loan +: new.amount. Точка - триггеры усложняются ... и даже исправлены (сохраняют целостность данных), будут иметь проблемы с масштабируемостью от блокировки. – KevinKirkpatrick