简单的 SQL oracle 触发器

Posted

技术标签:

【中文标题】简单的 SQL oracle 触发器【英文标题】:Simple SQL oracle trigger 【发布时间】:2015-09-03 12:06:30 【问题描述】:

您好,我正在为我的数据库创建一个基本的 SQL 触发器。本质上,我的数据库是一个假银行系统。加载文件如下图所示

-- prefix a2 is to

DROP TABLE a2_loanr;
DROP TABLE a2_accr;
DROP TABLE a2_customer;
DROP TABLE a2_account;
DROP TABLE a2_loan;
DROP TABLE a2_bankbranch;
DROP TABLE a2_bank;

CREATE TABLE a2_bank (
routingcode   VARCHAR(200)  PRIMARY KEY,
name          VARCHAR(200)  NOT NULL,
address       VARCHAR(200)  NOT NULL
);

INSERT INTO a2_bank VALUES
( '123456','ASB', '3 gladstone rd');
INSERT INTO a2_bank VALUES
( '123556','BNZ', '5 gladstone rd');
INSERT INTO a2_bank VALUES
( '12456','KIWIBANK', '3 gladstone rd');


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     VARCHAR(200)  NOT NULL,
FOREIGN KEY(routing_code) REFERENCES a2_bank(routingcode),
PRIMARY KEY(branch_num, routing_code)
);
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         VARCHAR(200)  NOT NULL,
contract_date  DATE          NOT NULL
);

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

CREATE TABLE a2_account (
acc_num       CHAR(10)  PRIMARY KEY,
type           VARCHAR(20)  NOT NULL,
balance         VARCHAR(10)  NOT NULL
);
INSERT INTO a2_account VALUES
( '2539267332', 'Savings', '20');
INSERT INTO a2_account VALUES
( '8237893378', 'Cash', '300');
INSERT INTO a2_account VALUES
( '2378723936', 'Cheque', '75');
INSERT INTO a2_account VALUES
( '2378723937', 'Savings', '175');


CREATE TABLE a2_customer (
ird_num         CHAR(8)  PRIMARY KEY,
name            VARCHAR(200)  NOT NULL,
address         VARCHAR(200)  NOT NULL,
phone           VARCHAR(20)
);
INSERT INTO a2_customer VALUES
( '25362672',  'Stan Yel', '5 Wanna way', '02010201');
INSERT INTO a2_customer VALUES
( '83783783', 'Cam Birch', '34 Trada st', '02302020202');
INSERT INTO a2_customer VALUES
( '23723367', 'Jeff King', '5 Queens st', '38982383');
INSERT INTO a2_customer VALUES
( '54637822',  'John Smith', '24 Queen st', '38922383');


CREATE TABLE a2_accr (
ird_num                CHAR(8)  NOT NULL ,
account_num            CHAR(10)  NOT NULL,
FOREIGN KEY(ird_num) REFERENCES a2_customer(ird_num),
FOREIGN KEY(account_num) REFERENCES a2_account(acc_num)
);
INSERT INTO a2_accr VALUES
( '25362672', '2539267332');
INSERT INTO a2_accr VALUES
( '83783783', '8237893378');
INSERT INTO a2_accr VALUES
( '83783783', '2378723937');

CREATE TABLE a2_loanr (
ird_num                CHAR(8)  NOT NULL ,
loan_num            CHAR(10)  NOT NULL,
FOREIGN KEY(ird_num) REFERENCES a2_customer(ird_num),
FOREIGN KEY(loan_num) REFERENCES a2_loan(loan_num)
);
INSERT INTO a2_loanr VALUES
( '54637822', '323');
INSERT INTO a2_loanr VALUES
( '23723367', '33');

COMMIT;

使用这个数据库,我希望创建派生属性“total_loan”,它只是每个银行分行在任何给定时刻的贷款总额。 (每个分行a2_bankbranch的贷款总额)

目前我将这段代码放在一个名为 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 amount ON a2-loan
FOR EACH ROW
BEGIN
IF INSERTING THEN
UPDATE a2_bankbranch
SET total_loan =
WHERE
ELSIF UPDATING THEN
UPDATE a2_bankbranch
SET total_loan =
WHERE
ELSE --deleting
UPDATE a2_bankbranch
SET total_loan =
WHERE
END;

目前我正在努力让触发器正常工作。 还有如何通过我的 load.sql 文件运行触发器?

【问题讨论】:

【参考方案1】:

触发器响应对表的插入、更新和删除。因此,在插入任何数据之前,您必须确保触发器已到位。

但是,在这种情况下,使用触发器没有任何意义,因为您可以即时计算总和。

【讨论】:

不幸的是,随着数据库变得越来越大,将需要触发器来跟上!另外,我需要知道如何在未来实施它们。如何让我的 load.sql 文件运行我的 trig.sql 文件,或者这是不可能的?【参考方案2】:

触发器响应INSERTUPDATE 和/或DELETE。 您的触发器有一个 WHERE,它没有任何价值。

我认为您的触发器的设置很好,但是您需要仔细查看是否可以在特定情况下进行查询。您不能UPDATE 没有要更新的行。

也请看这里,这里他们解释了如何设置触发器:enter link description here

编辑:

我也会在您的表格中添加一些内容:

表“a2_bankbranch”: 添加“Id”列并将其设置为PRIMARY KEY。 表“a2_loan”: 在需要填写“a2_bankbranch.Id”的地方添加一列“BankId”,同样填写NOT NULL

这样,您可以在触发器中使用它来计算每家银行的“a2_loan.Amount”总金额。

【讨论】:

【参考方案3】:

所以我意识到这不是一个真正的系统,而是......

您无法使用触发器成功维护摘要记录,因为如果同时修改两行,则触发器的每次执行都不会看到另一个会话中所做的更改。唯一的解决方案是提供一种锁定机制来序列化对分支表的访问。

您还可以异步更新分支记录,只需安排一个每小时/每天运行的计划作业来执行更新。

或者,您可以使用快速刷新的物化视图按分行汇总贷款数据,这也是一种能够报告每日/每月贷款、总金额等的有效方式。

【讨论】:

以上是关于简单的 SQL oracle 触发器的主要内容,如果未能解决你的问题,请参考以下文章

Oracle的基本语法,存储函数及触发器

oracle触发器中定时执行sql

oracle触发器疑问

oracle,sql,触发器

ORACLE触发器中如何终止SQL语句

oracle如何用sql查看触发器?