Скорректировать строки таблицы после внесения изменений (удалить, вставить обновление) в Oracle

#oracle #plsql

#Oracle #plsql

Вопрос:

В таблице «Типы» порядок строк должен контролироваться полем «ordem».

После любых изменений данных (удалить, вставить или обновить) остальные строки должны быть изменены, чтобы обеспечить правильное отображение содержимого.

Чтобы реализовать эту функциональность, я попытался закодировать триггер для исправления значений двумя аналогичными способами (I, II).

 
CREATE TABLE TYPES (
    ID          NUMBER          PRIMARY KEY,
    ARG_1       VARCHAR2(20)        NOT NULL,
    ARG_2       VARCHAR2(20)        NOT NULL,
    ORDEM       NUMBER              NOT NULL
);

-----------------------------------------------  
-- I
----------------------------------------------- 

CREATE OR REPLACE TRIGGER TGR_TYPES
  AFTER INSERT OR UPDATE OR DELETE ON TYPES
  DECLARE
    V_NORDEM NUMBER := NEW.ORDEM;    
    CURSOR C_TYPES IS
       SELECT ID, ORDEM
         FROM TYPES  
        WHERE ORDEM >= V_NORDEM;
  BEGIN 
    IF UPDATING OR INSERTING THEN
        BEGIN     
            FOR R_TYPE IN C_TYPES LOOP
                UPDATE TYPEA SET ORDEM = (ORDEM   1) WHERE ID = R_TYPE.ID;
             END LOOP;
        END;
    ELSE
        DECLARE V_ORDEM NUMBER := 0;
        BEGIN
            FOR R_TYPE IN C_TYPES LOOP
                UPDATE OSP_TP_ADDR_COMPLEMENTOS SET ORDEM = (V_ORDEM   1) WHERE ID = R_COMPLEMENTO.ID;
            END LOOP;
        END;
    END IF;
  END;

  /*
  ERROR ON COMPILE:

    ORA-04082: referências NEW ou OLD não permitidas nos gatilhos de nível de tabela
    04082. 00000 -  "NEW or OLD references not allowed in table level triggers"
    *Cause:    The trigger is accessing "new" or "old" values in a table trigger.
    *Action:   Remove any new or old references.

  */

-----------------------------------------------  
-- II 
----------------------------------------------- 
CREATE OR REPLACE
  TRIGGER TRG_TYPES
  AFTER INSERT OR UPDATE OR DELETE ON TYPES
  FOR EACH ROW

  BEGIN 
    IF UPDATING OR INSERTING THEN
        BEGIN     
            FOR TP IN (
                SELECT *
                FROM TYPES  
                WHERE ORDEM >= :NEW.ORDEM
            ) LOOP
                UPDATE TYPES SET ORDEM = (ORDEM   1) WHERE ID = TP.ID;
                COMMIT;
             END LOOP;
        END;
    ELSE
        DECLARE V_ORDEM NUMBER := 0;
        BEGIN
            FOR TP IN (
                SELECT *
                FROM TYPES
                ORDER BY ORDEM
            ) LOOP
                UPDATE TYPES SET ORDEM = (V_ORDEM   1) WHERE ID = TP.ID;
             END LOOP;
        END;
    END IF;
  END;

  /*
  ERROR ON UPDATE:

    UPDATE TYPES 
    SET ORDEM = 14
    WHERE ID=26
    Relatório de erros -
    ORA-04091: a tabela TYPES é mutante; talvez o gatilho/função não possa localizá-la
    ORA-06512: em "", line 9
    ORA-04088: erro durante a execução do gatilho ''
  */
  

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

Комментарии:

1. IOT здесь не поможет, IOT касается только хранилища, а не содержимого данных. Один вопрос о вашей мотивации при написании триггера: ожидаете ли вы, что пользователь вашего приложения сможет контролировать порядок отображения строк?

2. «После любых изменений данных корректируйте другие строки» — это, безусловно, не очень хорошая идея. Можете ли вы уточнить свой вопрос? Что именно вы пытаетесь сделать? Какая логика стоит за упорядочением? Это просто последовательные числа?

3. Это действительно плохая идея. Порядок отображения — это возможность пользовательского интерфейса, поэтому это то, что должно обрабатываться на клиенте или уровне доступа к данным, скажем, путем сортировки по ключевому столбцу или чему-то столь же значимому. Но чтобы действительно понять, почему это плохая идея, рассмотрим следующий сценарий: вы вставляете новую запись, в то же время я удаляю существующую запись — каким должен быть порядок теперь?