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