powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Пересечение интервалов
23 сообщений из 23, страница 1 из 1
Пересечение интервалов
    #39340415
Baturin Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый вечер!

не очень разбираюсь в Oracle, хотел узнать мнение профессионалов
Имеется таблица с колонками DATE_BEGIN и DATE_END, необходимо при добавлении записей проверять, чтобы новые записи не пересекались с уже имеющимися по дате.
Вот такой код вроде работает.
Хотелось бы узнать
1. корректен ли он?
2. будет ли он работать, если данные будут добавлять/изменять из нескольких сессий ?
3. где лучше добавлять такого рода проверки - на уровне приложения, на уровне БД или имеются иные варианты ?

Код: 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.
49.
  CREATE TABLE t 
   (	id integer NOT NULL,
	DATE_BEGIN DATE,
	DATE_END DATE,
	PRIMARY KEY (id),
	check (DATE_BEGIN < DATE_END) 
   );


  CREATE OR REPLACE TRIGGER CHK_CONSISTENCY
   after insert or update of id,DATE_BEGIN,DATE_END on t
   declare l_exst integer;
begin  

  select count(*) into l_exst from t t WHERE 
    exists(select 1 from t ti where t.id <> ti.id
    and ( (ti.DATE_BEGIN between t.DATE_BEGIN and t.DATE_END)
      or (ti.DATE_END between t.DATE_BEGIN and t.DATE_END) ) 
    );

  if l_exst > 0 then 
        RAISE_APPLICATION_ERROR( -20001, 'Overlapped !!!' );
   end if; 
end;


ALTER TRIGGER CHK_CONSISTENCY ENABLE;



INSERT INTO t
(
	id,
	DATE_BEGIN,
	DATE_END
)
select 1, to_date('2001-11-01 10:00:00','YYYY-MM-DD HH24:MI:SS'), to_date('2001-11-01 11:30:00','YYYY-MM-DD HH24:MI:SS') from dual
union all
select 2, to_date('2001-11-01 15:00:00','YYYY-MM-DD HH24:MI:SS'), to_date('2001-11-01 16:30:00','YYYY-MM-DD HH24:MI:SS') from dual
union all
select 3, to_date('2001-11-01 11:45:00','YYYY-MM-DD HH24:MI:SS'), to_date('2001-11-01 13:15:00','YYYY-MM-DD HH24:MI:SS') from dual;

INSERT INTO t
(
	id,
	DATE_BEGIN,
	DATE_END
)
select 4, to_date('2001-11-01 16:00:00','YYYY-MM-DD HH24:MI:SS'), to_date('2001-11-01 17:30:00','YYYY-MM-DD HH24:MI:SS') from dual;



Заранее благодарен за полезную информацию
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39340416
Baturin Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Забыл версию указать, если это критично
Код: plsql
1.
select * from v$version


Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39340421
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Baturin Alexey2. будет ли он работать, если данные будут добавлять/изменять из нескольких сессий ?Не будет.
На форуме были примеры, как муторно можно реализовать такую целостность декларативно.
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39340778
Baturin Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Тему можно закрывать, благодарю за коммент

для себя сделал вывод, чтобы грамотно реализовать такое,
необходимо закрывать прямой доступ к INSERT INTO t, т.к. доступ не будет синхронизирован
а для добавления/изменения данных в t использовать процедуру и в ней осуществлять синхронизацию доступа к таблице t, например через запрос

select resource_name into l_resource_name
from another_table
where resource_name = p_resource_name
FOR UPDATE;

далее проверять запросом пересечение интервалов уже в таблице t, и уже вызывать исключение или commit транзакции

подробнее написано по этой ссылке https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:42171194352295
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39340864
Фотография orawish
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Baturin AlexeyТему можно закрывать, благодарю за коммент

для себя сделал вывод, чтобы грамотно реализовать такое,
необходимо закрывать прямой доступ к INSERT INTO t, т.к. доступ не будет синхронизирован
а для добавления/изменения данных в t использовать процедуру и в ней осуществлять синхронизацию доступа к таблице t, например через запрос

select resource_name into l_resource_name
from another_table
where resource_name = p_resource_name
FOR UPDATE;

далее проверять запросом пересечение интервалов уже в таблице t, и уже вызывать исключение или commit транзакции

подробнее написано по этой ссылке https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:42171194352295

2787115
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39340866
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Baturin AlexeyТему можно закрывать, благодарю за коммент

для себя сделал вывод, чтобы грамотно реализовать такое,
необходимо закрывать прямой доступ к INSERT INTO t, т.к. доступ не будет синхронизирован
а для добавления/изменения данных в t использовать процедуру и в ней осуществлять синхронизацию доступа к таблице t, например через запрос

select resource_name into l_resource_name
from another_table
where resource_name = p_resource_name
FOR UPDATE;

далее проверять запросом пересечение интервалов уже в таблице t, и уже вызывать исключение или commit транзакции

подробнее написано по этой ссылке https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:42171194352295

Похоже ты прочитал Тома по-диагонали. Том предложил это решeние только потому что "вопрошавший" был на Oracle 9i и "отверг" materialized view решeние только потому что оно на 9i не работает. Надеюсь ты не на 9i?

SY.
P.S. Очень часто читая Тома люди берут предложенные им решения без учета того что этому решению 2, 3, 5 а то и 10 лет а Oracle на месте не стоит...
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39340900
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так, для побалoваться:

Код: 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.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
DROP TABLE T PURGE
/
DROP TABLE T_EXPANDED PURGE
/
  CREATE TABLE t 
   (	id integer NOT NULL,
	DATE_BEGIN DATE,
	DATE_END DATE,
	PRIMARY KEY (id),
	check (DATE_BEGIN < DATE_END) 
   );
  CREATE TABLE t_expanded 
   (	DATE_TAKEN DATE UNIQUE
   );


  CREATE OR REPLACE TRIGGER CHK_CONSISTENCY
   before insert
       or delete
       or update
          of DATE_BEGIN,
             DATE_END
   on t
   for each row
   begin
       delete  t_expanded
         where date_taken between :old.date_begin and :old.date_end;
       insert
        into t_expanded
          select  :new.date_begin + (level - 1) / 24 / 3600
            from  dual
            connect by :new.date_begin + (level - 1) / 24 / 3600 <= :new.date_end;
end;
/

SQL> INSERT INTO t
  2  (
  3   id,
  4   DATE_BEGIN,
  5   DATE_END
  6  )
  7  select 1, to_date('2001-11-01 10:00:00','YYYY-MM-DD HH24:MI:SS'), to_date('2001-11-01 11:30:00','YYYY-MM-DD HH24:MI:SS') from dual
  8  union all
  9  select 2, to_date('2001-11-01 15:00:00','YYYY-MM-DD HH24:MI:SS'), to_date('2001-11-01 16:30:00','YYYY-MM-DD HH24:MI:SS') from dual
 10  union all
 11  select 3, to_date('2001-11-01 11:45:00','YYYY-MM-DD HH24:MI:SS'), to_date('2001-11-01 13:15:00','YYYY-MM-DD HH24:MI:SS') from dual;

3 rows created.

SQL> 
SQL> INSERT INTO t
  2  (
  3   id,
  4   DATE_BEGIN,
  5   DATE_END
  6  )
  7  select 4, to_date('2001-11-01 16:00:00','YYYY-MM-DD HH24:MI:SS'), to_date('2001-11-01 17:30:00','YYYY-MM-DD HH24:MI:SS') from dual;
INSERT INTO t
            *
ERROR at line 1:
ORA-00001: unique constraint (SCOTT.SYS_C0014001) violated
ORA-06512: at "SCOTT.CHK_CONSISTENCY", line 4
ORA-04088: error during execution of trigger 'SCOTT.CHK_CONSISTENCY'


SQL> 



SY.
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39340923
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SYТак, для побалoваться:
Код: plsql
1.
(level - 1) / 24 / 3600

Не смешно. Больше похоже на скрытую рекламу какой-нибудь экзадаты.
Её, кстати, хватит для timestamp-а?
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39340925
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SY,

в t_expanded ID не надо?

....
stax
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39341014
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ElicНе смешно. Больше похоже на скрытую рекламу какой-нибудь экзадаты.
Её, кстати, хватит для timestamp-а?

А вот тут все зависит от интервала, поэтому и сказал - для баловства. Например если интервал по дням а не по секундам, то вполне рабочий вариант.
Даже по часам если интервал, скажем, между 1900г и 2100г:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
SQL> select (date '2100-01-01' - date '1900-01-01' + 1) * 24 n from dual;

                       N
------------------------
                 1753200

SQL> 



SY.
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39341149
SY,
Пример и правда интересный.
Но в реальности интервалы обычно привязаны к объектам, которых сто тыщ мильонов.
И в такой ситуации этот способ уже не прокатит'.
Вот если бы можно было чистить t_expanded по завершению транзакции, которая писала в таблицу с интервалами.
Есть в оракле какой-нито "триггер" на коммит?
Или что-то еще можно придумать?
Мне бы пригодились. (:
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39341151
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не согласенНо в реальности интервалы обычно привязаны к объектам, которых сто тыщ мильонов.В таком случае у тебя есть через что сериализовать проверку - блокировкой проверяемого объекта.
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39341196
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не согласенВот если бы можно было чистить t_expanded по завершению транзакции, которая писала в таблицу с интервалами.


Не понял.

Не согласенЕсть в оракле какой-нито "триггер" на коммит?


Есть - через refresh on commit materialized view.

А так, ждать пока Oracle добавит поддержку констрейнтов к temporal validity.

SY.
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39341353
SY,
Данные в таблице t_expanded нужны только в период внесения изменений в интервалы и только по тем объектам, в интервалы которых вносятся изменения.
Как только началась запись в интервалы, даты блокируются в t_expanded.
Транзакция завершилась - блокировки очищены.
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39341393
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не понял. Таблица t_expanded обязана хранить все точки всех интервалов объекта из таблицы t. Так-что в триггере придется заполнять t_expanded точками всех ужe существующих интервалов объекта что eсть мутация, не говоря уже о производительности.

SY.
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39341516
SY,

Производительность, несомненно, просядет, но 4К записей на объект на десятилетие терпимо.
Тем более, что изменение данных на глубину больше года обычно заблокировано, то можно и четырьмя сотнями обойтись.
Мутация тоже не сильно пугает. Т.к. первоначальное заполнение нужно сделать только по тем интервалам, которые были закоммичены до старта транзакции.
Меня смущает другое. Возни с аккуратным заполнением t_expanded будет больше, чем с написанием скрипта, ищущим пересечение интервалов, с последующим разруливанием наложений
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39341548
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не согласенМутация тоже не сильно пугает. Т.к. первоначальное заполнение нужно сделать только по тем интервалам, которые были закоммичены до старта транзакции.


Ну и как-же ты её обойдешь? Нет, обойти конечно можно через пакет и набор триггеров но тот еще геморрой ну и производительность опять просядет.

SY.
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39342323
SY,

Я считал, что прагма автономус даёт в триггере доступ к данным закоммиченным до старта текущей транзакции, не вызывая мутацию.
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39342736
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не согласенЯ считал, что прагма автономус даёт в триггере доступ к данным закоммиченным до старта текущей транзакции, не вызывая мутацию.

И что тебe даст анонимная транзакция кроме потери транзакционности?

SY.
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39343064
SY,

Сначала под прагмой обновлю состояние в t_expanded по ранее закоммиченным интервалам.
Потом без прагмы обновлю состояние t_expanded по текущему dml.
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39343111
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
в любом случае, кроме матвью, будет полезно пару раз в день джоб запускать, для проверки корректности интервалов
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39343636
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не согласенСначала под прагмой обновлю состояние в t_expanded по ранее закоммиченным интервалам.
Потом без прагмы обновлю состояние t_expanded по текущему dml.

Ты сам сeбя послушай: "Данные в таблице t_expanded нужны только в период внесения изменений в интервалы и только по тем объектам, в интервалы которых вносятся изменения". Вот и обьяcни как и что ты внесешь в t_expanded и главное как и когда ты удалишь из t_expanded.

SY.
...
Рейтинг: 0 / 0
Пересечение интервалов
    #39343976
SY,
Три ха-ха. Закольцевались.;)
автор ... и главное как и когда удалить ...
С этого-то я и начал. авторвот если бы можно было чистить
19857379
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Пересечение интервалов
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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