Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Мутирование таблицы  [new]
pastkhuf
Member

Откуда:
Сообщений: 17
Здравствуйте. При записи пациента на прием проводится проверка на наличие у него приемов в промежутке (+-20 мин). Если есть, то запретить вставку. При вставке проблем не возникает, но при обновлении поля выдает ошибку о мутировании таблицы. Что это за ошибка и почему она возникает, я понимаю, но вот куда мне деть SELECT? Как обойти мутирование? Или на что его заменить?

create or replace trigger Available_Patient
before insert or update on APPOINTMENT
FOR EACH ROW follows check_schedule
DECLARE
count_app_of_pat NUMBER(10);
Available_Patients BOOLEAN :=FALSE;
ST DATE;
FN DATE;
POINTER DATE;
begin
SELECT Count(*) into count_app_of_pat 
FROM APPOINTMENT 
WHERE :new.policy_number = policy_number AND
data_appointment = :new.data_appointment AND
ABS(to_date(:new.time, 'hh24:mi') - to_date(time, 'hh24:mi'))*24*60<20;

Available_Patients := count_app_of_pat=0;

IF NOT (Available_Patients) THEN 
raise_application_error(-20011,'Пациент в это время на приеме!');
END IF;
END;
18 май 17, 22:39    [20494376]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
Q.Tarantino
Member

Откуда: Где-то рядом...
Сообщений: 9312
оракл так и пишет - "таблица мутирована"?
а номер ошибки там прилагается?
18 май 17, 22:45    [20494385]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
pastkhuf
Member

Откуда:
Сообщений: 17
Q.Tarantino,
автор
ORA-04091: table name is mutating, trigger/function may not see it
18 май 17, 22:50    [20494396]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
Vladimir Filin
Member

Откуда: Москва
Сообщений: 58
pastkhuf,
Oracle 11R2:
If you must use a trigger to update a mutating table, you can avoid the mutating-table error in either of these ways:

- Use a compound DML trigger (see "Using Compound DML Triggers to Avoid Mutating-Table Error").

- Use a temporary table.
19 май 17, 03:01    [20494589]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
Vladimir Filin
Member

Откуда: Москва
Сообщений: 58
Vladimir Filin,
Mutating-Table Restriction
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#g1699708

Using Compound DML Triggers to Avoid Mutating-Table Error
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/triggers.htm#CHDFEBFJ
19 май 17, 03:08    [20494591]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
pastkhuf
Member

Откуда:
Сообщений: 17
Vladimir Filin,
Я эту теорию заранее просмотрел, у меня проблема с практикой. Я не знаю, как в моем случаем писать составной триггер?
19 май 17, 05:09    [20494607]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
pastkhuf
Member

Откуда:
Сообщений: 17
Vladimir Filin, мне ее обновлять даже не надо, просто посчитать количество определенных строк
19 май 17, 05:17    [20494610]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
pastkhuf
Member

Откуда:
Сообщений: 17
Vladimir Filin, если записать в before statement, то вообще триггер никак не будет реагировать на вставку, а after всегда выдает ошибку, даже если в таблице нет строк
create or replace trigger testone
  for update on appointment
  compound trigger
    count_app_of_pat NUMBER(10);
    patient number(10);
    dat date;
    timeapp varchar2(5);
    
     before each row is
     begin
     dat := :new.data_appointment;
     timeapp := :new.time;
     patient := :new.policy_number;
     end before each row;
     
     after statement is
     begin
     SELECT Count(*) into count_app_of_pat  
     FROM APPOINTMENT 
     WHERE patient = policy_number AND
     data_appointment = dat AND
     ABS(to_date(timeapp, 'hh24:mi') - to_date(time, 'hh24:mi'))*24*60<20;

     IF NOT (count_app_of_pat=0) THEN 
     raise_application_error(-20011,'Пациент в это время на приеме!');
     END IF;
     end after statement;

end testone;
19 май 17, 05:34    [20494611]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
tru55
Member

Откуда: СПб
Сообщений: 19625
ТОП популярных вопросов конечно уже прочитал?
19 май 17, 09:25    [20494888]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
pastkhuf
Member

Откуда:
Сообщений: 17
tru55,
Да, конечно, поэтому и пишу, что не получается
19 май 17, 09:51    [20494977]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
pastkhuf
Member

Откуда:
Сообщений: 17
почему мне никто не хочет помочь, может я тему неудачно назвал...
19 май 17, 10:59    [20495401]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
env
Member

Откуда: Россия, Москва
Сообщений: 4820
pastkhuf,

А с чем связана реализация на уровне триггера?
Сколько сессий одновременно могут добавлять записи по одному пациенту?
19 май 17, 11:03    [20495414]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
pastkhuf
Member

Откуда:
Сообщений: 17
env,
задача: если у пациента есть уже прием, то его нельзя записать на прием в интервале 20 мин до и после.
Я считаю в триггере эти строки, если их количество не равно 0, но запретить вставку.

Несколько сессий
19 май 17, 11:09    [20495448]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
Anatoly B
Member

Откуда:
Сообщений: 163
pastkhuf,
     IF NOT (count_app_of_pat=0) THEN 

Почему сравнение с нулем?
проапдейтили/вставили одну запись, запросом ее нашли,сравнили с нулем....
19 май 17, 11:14    [20495481]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
pastkhuf
Member

Откуда:
Сообщений: 17
Anatoly B,
я делаю то же самое. Если количество запей в интервале 20 мин не равно нулю, то запрещаю вставку. Там с логикой все хорошо, проблема в том, что оракл не дает возможность считывать данные из той же таблицы. То есть если бы я считал что-то из другой таблицы, ошибки бы не было
19 май 17, 11:24    [20495543]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
SQL*Plus
Member

Откуда: Россия, Москва
Сообщений: 7738
pastkhuf,

Выполняйте команду SELECT в триггере типа AFTER уровня statement (не for each row!).
Для такого триггера уже будет согласованное состояние данных таблицы и вы сможете избежать описываемых ошибок.
19 май 17, 13:06    [20496137]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
env
Member

Откуда: Россия, Москва
Сообщений: 4820
pastkhuf
Если количество запей в интервале 20 мин
, включая только что вставленную и потому попавшую в сравнение запись,
pastkhuf
не равно нулю

Да, действительно, с чего бы тут ошибке быть...
Ведь тут
pastkhuf
с логикой все хорошо, проблема в том, что оракл не дает
19 май 17, 13:46    [20496377]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
pastkhuf
Member

Откуда:
Сообщений: 17
SQL*Plus,
Ну мне же нужно предотвратить вставку, если пациент в это время на приеме!
Даже если так, я ж в составном триггере выполняю SELECT в after statement?
19 май 17, 13:47    [20496380]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
pastkhuf
Member

Откуда:
Сообщений: 17
env,
прошу прощения, признаю ошибку, но я имел введу в первом запросе не ошибки, когда я SELECT выполнял до вставки. Теперь все работает, спасибо всем большое!
Я правильно понимаю: after statemen срабатывает после вставки, тогда, если возникает ошибка, то результат откатывается?
19 май 17, 14:01    [20496446]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
XMLer
Member

Откуда:
Сообщений: 92
env
pastkhuf,

А с чем связана реализация на уровне триггера?
Сколько сессий одновременно могут добавлять записи по одному пациенту?

100500 сессий. Как это влияет на выбор уровня триггера.
19 май 17, 14:34    [20496597]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
непересекающиеся интервалы
Guest
XMLer
env
pastkhuf,

А с чем связана реализация на уровне триггера?
Сколько сессий одновременно могут добавлять записи по одному пациенту?

100500 сессий. Как это влияет на выбор уровня триггера.
это влияет на выбор уровня изоляции, блокировки таблицы или иных до/вместо триггерных действий по обеспечению целостности.
19 май 17, 14:43    [20496639]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
-2-
Member

Откуда:
Сообщений: 12899
pastkhuf
наличие у него приемов в промежутке (+-20 мин)
достаточно уникального индекса.
19 май 17, 14:52    [20496681]     Ответить | Цитировать Сообщить модератору
 Re: Мутирование таблицы  [new]
Vladimir Filin
Member

Откуда: Москва
Сообщений: 58
pastkhuf
Теперь все работает, ...

Вот и славно! После торжественного омывания нового триггера в достойной жидкости, есть смысл спокойно почитать пару (как минимум) тем про подобные задачки. На усмотрение pastkhuf, разумеется.
  • dbms_photoshop
    .... Читай эту тему Задачка

  • Владимир Бегун
    Базовая идея тут. Это не триггер, но для некоторых случаев позволяет решить задачку. Кодирование, обход мутаций и обеспечение целостности данных при конкурентном изменении данных в таблице -- это ряд вещей, над которыми приходится задумываться решая эту и подобные ей задачи используя DIY-методы.
  • 19 май 17, 14:58    [20496709]     Ответить | Цитировать Сообщить модератору
     Re: Мутирование таблицы  [new]
    XMLer
    Member

    Откуда:
    Сообщений: 92
    непересекающиеся интервалы
    иных до/вместо триггерных действий по обеспечению целостности.

    Триггер- инструмент, обеспечение целостности- целевая функция. Инструменты могут быть разные, уникальный индекс- на мой взгляд, предпочтительнее.
    19 май 17, 15:01    [20496727]     Ответить | Цитировать Сообщить модератору
     Re: Мутирование таблицы  [new]
    pastkhuf
    Member

    Откуда:
    Сообщений: 17
    -2-,
    недостаточно. Если я хочу записаться на 11:30, то у меня не должно быть приемов с 11:10 по 11:50
    19 май 17, 15:06    [20496748]     Ответить | Цитировать Сообщить модератору
    Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
    Все форумы / Oracle Ответить