powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Мутирование таблицы
44 сообщений из 44, показаны все 2 страниц
Мутирование таблицы
    #39455709
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте. При записи пациента на прием проводится проверка на наличие у него приемов в промежутке (+-20 мин). Если есть, то запретить вставку. При вставке проблем не возникает, но при обновлении поля выдает ошибку о мутировании таблицы. Что это за ошибка и почему она возникает, я понимаю, но вот куда мне деть SELECT? Как обойти мутирование? Или на что его заменить?

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
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;
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39455710
Q.Tarantino
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
оракл так и пишет - "таблица мутирована"?
а номер ошибки там прилагается?
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39455712
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Q.Tarantino, авторORA-04091: table name is mutating, trigger/function may not see it
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39455756
Фотография Vladimir Filin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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.
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39455757
Фотография Vladimir Filin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39455765
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Vladimir Filin,
Я эту теорию заранее просмотрел, у меня проблема с практикой. Я не знаю, как в моем случаем писать составной триггер?
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39455768
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Vladimir Filin, мне ее обновлять даже не надо, просто посчитать количество определенных строк
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39455769
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Vladimir Filin, если записать в before statement, то вообще триггер никак не будет реагировать на вставку, а after всегда выдает ошибку, даже если в таблице нет строк
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
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;
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39455834
tru55
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ТОП популярных вопросов конечно уже прочитал?
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39455849
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tru55,
Да, конечно, поэтому и пишу, что не получается
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39455927
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
почему мне никто не хочет помочь, может я тему неудачно назвал...
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39455928
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pastkhuf,

А с чем связана реализация на уровне триггера?
Сколько сессий одновременно могут добавлять записи по одному пациенту?
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39455936
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
env,
задача: если у пациента есть уже прием, то его нельзя записать на прием в интервале 20 мин до и после.
Я считаю в триггере эти строки, если их количество не равно 0, но запретить вставку.

Несколько сессий
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39455947
Anatoly B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
pastkhuf,
Код: plsql
1.
     IF NOT (count_app_of_pat=0) THEN 


Почему сравнение с нулем?
проапдейтили/вставили одну запись, запросом ее нашли,сравнили с нулем....
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39455962
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly B,
я делаю то же самое. Если количество запей в интервале 20 мин не равно нулю, то запрещаю вставку. Там с логикой все хорошо, проблема в том, что оракл не дает возможность считывать данные из той же таблицы. То есть если бы я считал что-то из другой таблицы, ошибки бы не было
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456069
SQL*Plus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pastkhuf,

Выполняйте команду SELECT в триггере типа AFTER уровня statement (не for each row!).
Для такого триггера уже будет согласованное состояние данных таблицы и вы сможете избежать описываемых ошибок.
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456115
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pastkhufЕсли количество запей в интервале 20 мин, включая только что вставленную и потому попавшую в сравнение запись, pastkhufне равно нулю
Да, действительно, с чего бы тут ошибке быть...
Ведь тут
pastkhufс логикой все хорошо, проблема в том, что оракл не дает
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456117
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SQL*Plus,
Ну мне же нужно предотвратить вставку, если пациент в это время на приеме!
Даже если так, я ж в составном триггере выполняю SELECT в after statement?
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456132
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
env,
прошу прощения, признаю ошибку, но я имел введу в первом запросе не ошибки, когда я SELECT выполнял до вставки. Теперь все работает, спасибо всем большое!
Я правильно понимаю: after statemen срабатывает после вставки, тогда, если возникает ошибка, то результат откатывается?
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456169
XMLer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
envpastkhuf,

А с чем связана реализация на уровне триггера?
Сколько сессий одновременно могут добавлять записи по одному пациенту?
100500 сессий. Как это влияет на выбор уровня триггера.
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456180
XMLerenvpastkhuf,

А с чем связана реализация на уровне триггера?
Сколько сессий одновременно могут добавлять записи по одному пациенту?
100500 сессий. Как это влияет на выбор уровня триггера.это влияет на выбор уровня изоляции, блокировки таблицы или иных до/вместо триггерных действий по обеспечению целостности.
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456192
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pastkhufналичие у него приемов в промежутке (+-20 мин)достаточно уникального индекса.
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456204
Фотография Vladimir Filin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pastkhuf Теперь все работает, ...
Вот и славно! После торжественного омывания нового триггера в достойной жидкости, есть смысл спокойно почитать пару (как минимум) тем про подобные задачки. На усмотрение pastkhuf, разумеется.
dbms_photoshop.... Читай эту тему Задачка

Владимир Бегун Базовая идея тут . Это не триггер, но для некоторых случаев позволяет решить задачку. Кодирование, обход мутаций и обеспечение целостности данных при конкурентном изменении данных в таблице -- это ряд вещей, над которыми приходится задумываться решая эту и подобные ей задачи используя DIY-методы.
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456211
XMLer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
непересекающиеся интервалы иных до/вместо триггерных действий по обеспечению целостности.
Триггер- инструмент, обеспечение целостности- целевая функция. Инструменты могут быть разные, уникальный индекс- на мой взгляд, предпочтительнее.
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456215
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
-2-,
недостаточно. Если я хочу записаться на 11:30, то у меня не должно быть приемов с 11:10 по 11:50
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456230
XMLer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pastkhuf-2-,
недостаточно. Если я хочу записаться на 11:30, то у меня не должно быть приемов с 11:10 по 11:50
сделай табличку "минуты приема клиента", на неё повесь уникальный ключ. вставляй туда 40 строк из селекта.
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456242
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pastkhufнедостаточно. Если я хочу записаться на 11:30, то у меня не должно быть приемов с 11:10 по 11:50достаточно только уникального индекса.
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456272
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pastkhuf,

на правах шутки
Код: plsql
1.
select trunc(sysdate,'hh') + numtodsinterval(trunc((sysdate - trunc(sysdate,'hh'))*72)*20,'minute') from dual
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456279
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
XMLer,
зачем? у меня уже работает с составным триггером
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456283
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
-2-,
объясните, пожалуйста, как? а то я не понимаю
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456285
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pastkhufу меня уже работает с составным триггеромЭто тебе только кажется. Пока ты наивно думаешь, что твоя сессия - единственная во вселенной.
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456293
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ElicЭто тебе только кажется.
Ты не совсем прав, она и для нескольких сессий будет работать, просто не совсем так, как ожидается. :)
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456301
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Elic,
Хорошо, как мне тогда решить эту задачу, чтоб не было проблем в случае нескольких сессий?
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456307
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pastkhuf,

самое простое триггер-вспомогательная_табличка-уникальный_индекс
(если вариант тупым округлением не прокатывает).
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456308
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pastkhufХорошо, как мне тогда решить эту задачу, чтоб не было проблем в случае нескольких сессий? 20496827
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456325
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
простите, я начинаю не въезжать
Сергей Арсеньевpastkhuf,

(если вариант тупым округлением не прокатывает).
что округлять? время приема? зачем?

Сергей Арсеньевpastkhuf,

самое простое триггер-вспомогательная_табличка-уникальный_индекс.

Ну вот я стараюсь сам догадаться, но не получается. Для чего вспомогательная таблица, что там будет хранится? Что нам даст уникальный индекс?
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456338
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pastkhuf,

ну самое простое же
во вспомогательной табличке хранятся минуты (truncate(sysdate,'MI')+(level-21)/24/60)), которые заняты каждым вносимым талончиком и пациент.
Соответственно индекс на ней. Что занята минута может быть не более одного раза. :)
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456346
Фотография -2-
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ElicpastkhufХорошо, как мне тогда решить эту задачу, чтоб не было проблем в случае нескольких сессий? 20496827 Я соврал про только . Древнее решение от orawish также ограничивает "непрерывность" интервалов, а другое решение использовать матвью.
Или есть вариант?
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456362
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Упрощенный взгляд на проблему
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
create or replace type t_persondate as object (
  person number
 ,dt date
);
/

create or replace type tdate as table of t_persondate;
/

create or replace function pm20(person in number,p in date) return tdate
deterministic
is
 dt tdate;
begin
 select t_persondate(person,trunc(p+(level-1)/24/60,'MI')) bulk collect into dt from dual connect by level<22;
 return dt;
end;
/

create table test_t (
  person number not null
 ,dt date not null
 ,rg tdate
)
 NESTED TABLE rg store as test_t_store
;

create trigger test_t 
before insert or update on test_t 
for each row
begin
 :new.rg:=pm20(:new.person,:new.dt);
end;
/

create unique index test_t_ux on test_t_store(person,dt);

insert into test_t (person,dt)
 values (1,sysdate);

insert into test_t (person,dt)
 values (1,sysdate+21/24/60); 

insert into test_t (person,dt)
 values (1,sysdate+20/24/60);  
 
insert into test_t (person,dt)
 values (2,sysdate+11/24/60);  


...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456377
XMLer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pastkhuf
Ну вот я стараюсь сам догадаться, но не получается. Для чего вспомогательная таблица, что там будет хранится? Что нам даст уникальный индекс?
Код: plsql
1.
2.
3.
 select :CLIENT_ID, :WHORE_ID, TRUNC((:VIZIT_DATE) + (LEVEL - 20)/ 1440, 'mi') 
 from dual
 connect by level <= 40
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456413
pastkhuf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сергей Арсеньев, XMLer
Спасибо большое за подробный ответ! Я постараюсь все это понять, но, чувствую, мне нужно еще поучиться, иначе, если я продолжу тупить, я вас замучаю
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456523
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
XMLer
Код: plsql
1.
2.
3.
 select :CLIENT_ID, :WHORE_ID, TRUNC((:VIZIT_DATE) + (LEVEL - 20)/ 1440, 'mi') 
 from dual
 connect by level <= 40


У Вас будут ложноположительно перекрываться диапазоны.
Например 12:10+19 и 12:48-19 это 12:29 но между 12:10 и 12:48 чуть больше 20 минут
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39456752
SQL*Plus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pastkhufSQL*Plus,
Ну мне же нужно предотвратить вставку, если пациент в это время на приеме!
Даже если так, я ж в составном триггере выполняю SELECT в after statement?
Для предотвращения вызывайте в триггере RAISE_APPLICATION_ERROR
и обрабатывайте получаемую ошибку.
...
Рейтинг: 0 / 0
Мутирование таблицы
    #39457092
XMLer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей АрсеньевУ Вас будут ложноположительно перекрываться диапазоны.
Например 12:10+19 и 12:48-19 это 12:29 но между 12:10 и 12:48 чуть больше 20 минут
Вы правы, больше 20 минут, а точнее 40 минут. ТС пишет:
pastkhuf-Если я хочу записаться на 11:30, то у меня не должно быть приемов с 11:10 по 11:50
...
Рейтинг: 0 / 0
44 сообщений из 44, показаны все 2 страниц
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Мутирование таблицы
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]