有没有办法“减慢”触发器?
Posted
技术标签:
【中文标题】有没有办法“减慢”触发器?【英文标题】:Is there any way to "slow down" TRIGGERS? 【发布时间】:2018-11-01 01:37:57 【问题描述】:我在 Oracle SQL Developer 3.2.2 中使用 PL/SQL,使用 Oracle Database 11g Express Edition。
到目前为止,我已经创建了几个表:Population 和 Sectors。
CREATE TABLE sectores (
codS NUMBER(2),
nombreS VARCHAR2(20),
porcentS NUMBER(5,2),
ingresosS NUMBER(9,2),
num_pob NUMBER(3),
PRIMARY KEY (codS)
);
CREATE TABLE poblacion (
dni VARCHAR2(9),
nombre VARCHAR(12),
apellido1 VARCHAR2(12),
apellido2 VARCHAR2(12),
fechanac DATE,
direccion VARCHAR2(20),
cp VARCHAR2(5),
sexo VARCHAR2(1),
ingresos NUMBER(7,2),
gastosFijos NUMBER(7,2),
gastosAlim NUMBER(7,2),
gastosRopa NUMBER(7,2),
sector NUMBER(2),
PRIMARY KEY (dni),
FOREIGN KEY (sector) REFERENCES sectores (codS) ON DELETE SET NULL
);
因此,“人口”中的人将以某种方式与部门联系起来。 我的目的是随时检测我在同一个扇区中有超过 3 个人。
每当我在 Population 中插入一个新人时,我都会将 Sectors 中的 num_pob 增加 1。我用这个 TRIGGER 来做到这一点:
CREATE OR REPLACE TRIGGER ingresosS1
AFTER INSERT ON poblacion
REFERENCING NEW AS NUEVA
FOR EACH ROW
WHEN (NUEVA.sector IS NOT NULL)
BEGIN
UPDATE sectores
SET ingresosS = ingresosS + :NUEVA.ingresos
WHERE codS = :NUEVA.sector;
UPDATE sectores
SET num_pob = 1 + (SELECT num_pob FROM sectores WHERE codS = :NUEVA.sector)
WHERE codS = :NUEVA.sector;
UPDATE sectores
SET porcentS = 100 * ingresosS / (SELECT SUM(ingresosS) FROM sectores);
END;
/
我检查了这个,到目前为止一切正常。 现在,我声明这个触发器:
CREATE OR REPLACE TRIGGER muchaGente
AFTER INSERT OR UPDATE ON sectores
FOR EACH ROW
WHEN (NEW.codS IS NOT NULL)
DECLARE
counter INTEGER;
numPOB INTEGER;
BEGIN
counter := :OLD.num_pob;
numPOB := counter - 1;
IF 3 < counter
THEN
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_LINE('');
DBMS_OUTPUT.PUT_LINE('Trigger muchaGente: Hay más de 3 personas en el sector:' || :NEW.codS );
DBMS_OUTPUT.PUT_LINE('Trigger muchaGente: Antes había:' || numPOB ||', ahora:' || :OLD.num_pob );
DBMS_OUTPUT.PUT_LINE('');
END IF;
END;
/
每当我超过 3 人标记时,这个应该可以帮助我在屏幕上写字。当我在同一扇区中插入 4 个人时,它可以完美运行。这是我插入 4 个人后的日志:
Trigger muchaGente: Hay más de 3 personas en el sector:1
触发 muchaGente: Antes había:3, ahora:4
但是,问题来了...删除表并再次创建它们后,当我插入 5 个人时,我在日志中得到了这个:
Trigger muchaGente: Hay más de 3 personas en el sector:1
触发 muchaGente: Antes había:3, ahora:4
Trigger muchaGente: Hay más de 3 personas en el sector:1
触发 muchaGente: Antes había:3, ahora:4
Trigger muchaGente: Hay más de 3 personas en el sector:1
触发 muchaGente: Antes había:3, ahora:4
Trigger muchaGente: Hay más de 3 personas en el sector:1
触发 muchaGente: Antes había:4, ahora:5
这有 0 意义。我想不知何故,触发器的速度足以弄乱我屏幕上的日志,你们知道无论如何要解决这个问题吗?也许最后一个TRIGGER有错误,但我没有看到任何...
【问题讨论】:
【参考方案1】:DBMS_OUTPUT.PUT_LINE 将字符串放入缓冲区。这些仅在控制权返回客户端时显示。在缓冲输出的 PL/SQL 程序单元返回其调用者之前,无法检索输出。
当您的条件(每个扇区的 num_pob > 3)得到满足时,您应该考虑引发异常。
重写你的触发器。
触发器1
CREATE OR REPLACE TRIGGER ingresosS1
AFTER INSERT ON poblacion
REFERENCING NEW AS NUEVA
FOR EACH ROW
WHEN (NUEVA.sector IS NOT NULL)
BEGIN
UPDATE sectores
SET ingresosS = ingresosS + :NUEVA.ingresos
WHERE codS = :NUEVA.sector;
UPDATE sectores
SET num_pob = COALESCE(num_pob,0) + 1
WHERE codS = :NUEVA.sector;
UPDATE sectores
SET porcentS = COALESCE(100 * ingresosS / (SELECT SUM(ingresosS) FROM sectores),0);
END;
/
触发器2
CREATE OR REPLACE TRIGGER muchaGente
AFTER INSERT OR UPDATE ON sectores
FOR EACH ROW
WHEN (NEW.codS IS NOT NULL)
DECLARE
counter INTEGER;
numPOB INTEGER;
BEGIN
counter := :OLD.num_pob;
numPOB := counter - 1;
IF counter > 3
THEN
RAISE_APPLICATION_ERROR( -20001,
'There are more than 3 persons in the same Sector' );
END IF;
END;
/
所以,当条件满足时,会引发异常
ORA-20001:同一个扇区中超过 3 人
Demo
【讨论】:
哇,1 周前我正在处理异常,但我不知道我可以在这里使用它们。感谢您的解决方案和一开始的解释!以上是关于有没有办法“减慢”触发器?的主要内容,如果未能解决你的问题,请参考以下文章