Есть ли способ «замедлить» ТРИГГЕРС? - PullRequest
0 голосов
/ 01 ноября 2018

Я работаю с PL / SQL в Oracle SQL Developer 3.2.2, используя Oracle Database 11g Express Edition .

Пока я создал несколько таблиц: Население и Секторы.

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 человек в одном секторе.

Всякий раз, когда я вставляю нового человека в Население, я увеличиваю num_pob от Секторов на 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;
/

Этот должен помогать мне писать на экране каждый раз, когда я превышаю отметку 3 человека. Когда я вставляю 4 человека в одни и те же сектора, это работает отлично. Это мой журнал после вставки 4 человек:

Триггер мучаГенте: 3 человека в секторе: 1

Триггер мучаГенте: Antes había: 3, ахора: 4

Однако, и здесь возникает проблема ... После удаления таблиц и их повторного создания, когда я вставляю 5 человек, я получаю это в журнале:

Триггер мучаГенте: 3 человека в секторе: 1

Триггер мучаГенте: Antes había: 3, ахора: 4

Триггер мучаГенте: 3 человека в секторе: 1

Триггер мучаГенте: Antes había: 3, ахора: 4

Триггер мучаГенте: 3 человека в секторе: 1

Триггер мучаГенте: Antes había: 3, ахора: 4

Триггер мучаГенте: 3 человека в секторе: 1

Триггер мучаГенте: Antes había: 4, ахора: 5

Это имеет 0 смысла. Я думаю, что каким-то образом триггеры достаточно быстры, чтобы испортить журналы на моем экране. Ребята, вы все равно знаете, как это исправить? Может быть, последний TRIGGER имеет ошибку, но я не вижу ...

1 Ответ

0 голосов
/ 01 ноября 2018

DBMS_OUTPUT.PUT_LINE помещает строки в буфер. Они отображаются только тогда, когда управление возвращается клиенту. Выходные данные не могут быть получены до тех пор, пока программный модуль PL / SQL, из которого он был буферизован, не вернется к своему вызывающему.

Вам следует рассмотреть возможность создания исключения, если ваше условие (num_pob на сектор> 3) выполнено.

Переписать ваши триггеры.

Trigger1

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;
/

Trigger2

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 человек

Демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...