2015-06-22 3 views
-1

я создал таблицу следующим образом:Определить интервал при вводе значений в таблице

CREATE table screening 
(
    screening_id NUMBER(6,0) PRIMARY KEY, 
    plan_id NUMBER(4,0), 
    theatre_id NUMBER(1,0), 
    screening_date DATE, 
    screening_start_hh24 NUMBER(2,0) CHECK(screening_start_hh24 BETWEEN 9 AND 22), 
    screening_start_mm60 NUMBER(2,0) CHECK(screening_start_mm60 BETWEEN 0 AND 59), 
    CONSTRAINT fk_plan_id FOREIGN KEY(plan_id) 
    REFERENCES screening_plan(plan_id), 
    CONSTRAINT fk_theatre_id_screening FOREIGN KEY(theatre_id) 
    REFERENCES theatre(theatre_id) 
) 

«screening_start_hh24» для времени начала в час и «screening_start_mm60» для времени запуска в течение нескольких минут. Что мне делать, чтобы добавить разрыв не менее 30 минут между двумя последовательными экранами в одном и том же театре? Я использую оракул.

+0

Это вообще не то, что вы определяете в декларативных ограничениях. Обычно это бизнес-правило, которое вы реализуете в хранимой процедуре, которая вставляет данные в эту таблицу. Кроме того, поскольку 'screening_date' является' date', он будет иметь по сути день и время. Нет смысла выделять время на два дополнительных столбца, предположительно устанавливая время на 'screening_date' до полуночи, а не просто устанавливая' screening_date' правильно. –

+0

Я понимаю тот факт, что screening_date также будет иметь время. Вместо того, чтобы извлекать время с даты, которое будет использовать больше времени процессора, будет лучше добавить два столбца. Помимо хранимой процедуры, нет ли другого способа определить ее, создав таблицу? – BinaryTerror

+1

Хранение времени отдельно нарушает в основном каждое правило нормализации. Я предполагаю, что вы провели бенчмаркинг, который показывает, что узкое место вашего приложения действительно извлекает время из столбца «date» и что эта денормализация действительно устраняет это узкое место. Невозможно создать ограничение, пересекающее строки. Вы можете создать материализованное представление 'on commit', которое хранит следующую дату скрининга в той же строке и помещает ограничение на материализованное представление, если вы действительно определились. –

ответ

0

Создание хранимой процедуры (в или из пакета), чтобы добавить скрининги и реализовать логику в том, что:

CREATE SEQUENCE screening_seq; 
/
CREATE OR REPLACE PACKAGE screening_pkg AS 
    PROCEDURE addScreening(
    i_plan_id IN screening.plan_id%TYPE, 
    i_theatre_id IN screening.theatre_id%TYPE, 
    i_start IN screening.screening_date%TYPE, 
    o_error OUT VARCHAR2 
); 
END screening_pkg; 
/
CREATE OR REPLACE PACKAGE BODY screening_pkg AS 
    PROCEDURE addScreening(
    i_plan_id IN screening.plan_id%TYPE, 
    i_theatre_id IN screening.theatre_id%TYPE, 
    i_start  IN screening.screening_date%TYPE, 
    o_error  OUT VARCHAR2 
) 
    AS 
    BEGIN 
    DECLARE 
     v_exists NUMBER(1,0); 
    BEGIN 
     SELECT 1 
     INTO v_exists 
     FROM screening 
     WHERE theatre_id = i_theatre_id 
     AND screening_date BETWEEN i_start - INTERVAL '30' MINUTE 
          AND  i_start + INTERVAL '30' MINUTE; 

     o_error := 'Screening exists within 30 minutes.'; 
     RETURN; 
    EXCEPTION 
     WHEN NO_DATA_FOUND THEN 
     NULL; 
    END; 

    INSERT INTO screening (
     screening_id, 
     plan_id, 
     theatre_id, 
     screening_date, 
     screening_start_hh24, 
     screening_start_mm60 
    ) VALUES (
     screening_seq.NEXTVAL, 
     i_plan_id, 
     i_theatre_id, 
     i_start, 
     TO_NUMBER(TO_CHAR(i_start, 'HH24')), 
     TO_NUMBER(TO_CHAR(i_start, 'MI')) 
    ); 
    END addScreening; 
END screening_pkg; 
/

Кроме того, вам не нужны часы и минуты столбцы - вы можете просто использовать столбец даты.

+0

Спасибо за подробный ответ. – BinaryTerror

Смежные вопросы