Убедитесь, что строка Oracle представляет уникальный промежуток времени

Мне нужно сделать процесс в Oracle/PLSQL. Я должен убедиться, что интервал времени между start_date и end_date из новой строки, которую я создаю, не должен пересекаться с другими start_dates и end_dates из других строк.

Теперь мне нужно проверить каждую строку на наличие этого условия, и если оно не соответствует, повторяющаяся инструкция должна остановиться, а после этого отобразить сообщение, такое как "Указанный интервал времени неверен".

Я не знаю, как создавать повторяющиеся инструкции в Oracle/PLSQL, и я был бы признателен, если бы вы мне помогли.

Мне нужен цикл или что-то подобное, чтобы проверить каждую строку в моей таблице, что интервал времени, заданный date_hour_i и date_hour_e, не пересекает другие интервалы времени, заданные остальными строками. Еще одно уточнение....даты из каждой строки соответствуют клиенту и сотруднику, который делает стрижку клиенту в заданном интервале времени....и я хочу как-то не дать вводить новую строку, если для тот же клиент (или другой клиент) и сотрудник, новый интервал времени пересекает другие интервалы времени с тем же/другим клиентом и сотрудником.... надеюсь, я ясно выразился...


person Dan F.    schedule 24.05.2010    source источник
comment
На самом деле, это это вопрос. Просто опубликуйте структуру таблицы, о которой вы говорите.   -  person eKek0    schedule 24.05.2010
comment
Oracle PL/SQL — это расширение SQL, языка структурированных запросов. Попробуйте мыслить с точки зрения заданных операций, а не процедурных шагов. Вместо проверки каждой строки вам нужно запросить все строки, которые соответствуют определенному условию.   -  person Jeffrey Kemp    schedule 25.05.2010


Ответы (4)



зачем проверять каждую строку? просто запросите время начала и окончания. если результат > 0, вывести сообщение об ошибке, иначе вставить.

person Jan K.    schedule 24.05.2010

я предполагаю, что это будет во время триггера BEFORE INSERT OR UPDATE.

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

Вы можете обойти это, используя PRAGMA AUTONOMOUS_TRANSACTION для создания нового потока.

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

CREATE OR REPLACE TRIGGER mytrigger
BEFORE INSERT OR UPDATE ON mytable FOR EACH ROW
DECLARE 
    cnt number;
BEGIN 
    SELECT count(*) into cnt
    FROM reserved_date_range                
    WHERE :new.begin_date BETWEEN begin_dt and end_dt

    if ( cnt > 0 ) then
        raise_application_error(-20000,'Overlapping date ranges');
    else
        insert into reserved_date_range( begin_dt, end_dt ) 
        values ( :new.begin_date, :new.end_date );
    end if;
End;
/
person Randy    schedule 24.05.2010
comment
Мне нужен цикл или что-то подобное, чтобы проверить каждую строку в моей таблице, что интервал времени, заданный date_hour_i и date_hour_e, не пересекает другие интервалы времени, заданные остальными строками. Еще одно уточнение....даты из каждой строки соответствуют клиенту и сотруднику, который делает стрижку клиенту в заданном интервале времени....и я хочу как-то не дать вводить новую строку, если для тот же клиент и сотрудник, новый интервал времени пересекает другие интервалы времени с тем же клиентом и сотрудником.... надеюсь, я ясно выразился... - person Dan F.; 25.05.2010
comment
Опять же, проблемы параллелизма могут испортить это решение. Что, если другая вставка (скажем, другим пользователем) произойдет между операторами выбора и вставки, и эта вставка будет перекрываться. Тогда все наши решения, которые сканируют таблицу на наличие перекрытий, потерпят неудачу. - person josephj1989; 25.05.2010
comment
приведенный выше триггер НЕ будет иметь проблемы с параллелизмом, потому что это происходит в триггере. РСУБД будет иметь согласованное по чтению представление управляющего запроса, а вставки будут выполняться последовательно. - person Randy; 25.05.2010
comment
Непротиворечивое представление чтения не препятствует вставке/обновлению других сеансов. Согласованность чтения обеспечивает только просмотр «истории» данных, если это необходимо. - person josephj1989; 26.05.2010

Скажем, ваша таблица - tab1, а дата начала - stdate, а дата окончания - endate, также пусть новая дата начала и новая дата окончания будут в переменных PLSQL v_stdate и v_endate.

поэтому ваша вставка может быть чем-то вроде

insert into tab1 (stdate,endate)
select v_stdate,v_endate  from dual
where not exists(
select 'overlap' from tab1 t1
where v_stdate between(t1.stdate and nvl(t1.endate,v_endate) 
or   v_endate between(t1.stdate and nvl(t1.endate,v_endate)

)

Решение этой проблемы немного сложно из-за проблем параллелизма. В вашем случае вы планируете событие (или ресурс). Итак, я полагаю, у вас есть таблица, содержащая ресурс (скажем, клиент). Прежде чем добавить другое расписание (или событие) для клиента, вы должны заблокировать конкретную запись клиента, например.

select client_id from Clients where client_id=p_client_id for update;

Затем вы можете убедиться, что нет перекрытий, вставить новое расписание и зафиксировать. В этот момент блокировка будет снята. Любое решение, не использующее объект сериализации, обязательно будет ошибочным из-за проблем с параллелизмом. Вы можете сделать это в своем PLSQL или в триггере After Insert. Но абсолютно необходимо заблокировать фактическую запись ресурса.

person josephj1989    schedule 24.05.2010