Sql 有没有什么办法可以;慢下来”;触发器?

Sql 有没有什么办法可以;慢下来”;触发器?,sql,oracle,plsql,triggers,Sql,Oracle,Plsql,Triggers,我在Oracle SQL Developer3.2.2中使用Oracle Database 11g Express Edition使用PL/SQL 到目前为止,我创建了几个表格:人口和部门 CREATE TABLE sectores ( codS NUMBER(2), nombreS VARCHAR2(20), porcentS NUMBER(5,2), ingresosS NUMBER(9,2), num_pob NUMBER(3), PRIMARY KEY (codS

我在Oracle SQL Developer3.2.2中使用Oracle Database 11g Express Edition使用PL/SQL

到目前为止,我创建了几个表格:人口和部门

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人以上的任何时候进行检测

每当我在人口中插入一个新人,我都会将部门的人口增长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 = 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;
/
我检查了这个,到目前为止一切正常。 现在,我宣布这个触发器:

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;
/
创建或替换触发器muchaGente
在扇区上插入或更新后
每行
当(NEW.codS不为空)
声明
计数器整数;
numPOB整数;
开始
计数器:=:OLD.num_pob;
numPOB:=计数器-1;
如果3<计数器
然后
DBMS_OUTPUT.ENABLE;
DBMS_OUTPUT.PUT_行(“”);
DBMS_OUTPUT.PUT_LINE('Trigger muchaGente:Hay más de 3 personas en el sector:'| |:NEW.codS);
DBMS|u OUTPUT.PUT|LINE('Trigger muchaGente:Antes había:'| | numPOB | |',ahora:'| |:OLD.num|pob);
DBMS_OUTPUT.PUT_行(“”);
如果结束;
结束;
/
每当我超过3人的分数时,这个应该可以帮助我在屏幕上写字。当我在相同的扇区中插入4个人时,它工作得非常好。这是我插入4个人后的日志:

触发因素:行业中的3个人:1

触发muchaGente:Antes había:3,ahora:4

然而,问题来了。。。在删除表并再次创建它们之后,当我插入5个人时,我会在日志中看到:

触发因素:行业中的3个人:1

触发muchaGente:Antes había:3,ahora:4

触发因素:行业中的3个人:1

触发muchaGente:Antes había:3,ahora:4

触发因素:行业中的3个人:1

触发muchaGente:Antes había:3,ahora:4

触发因素:行业中的3个人:1

触发muchaGente:Antes había:4,ahora:5

这毫无意义。我猜不知怎么的,触发器的速度快到足以把我屏幕上的日志搞乱,你们知道怎么解决这个问题吗?可能最后一个触发器有错误,但我没有看到任何…

将字符串放入缓冲区。这些仅在控件返回到客户端时显示。只有在缓冲它的PL/SQL程序单元返回到其调用方之前,才能检索输出

当您的条件(NuthPoPB每扇区> 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人以上


Woah,一周前我在处理异常,但我不知道我可以在这里使用它们。感谢您在乞讨会上的解答和解释!