ОШИБКА: - ›PLS-00382: выражение неправильного типа

что за сбой на триггере ???? Я пытаюсь создать триггер, который будет активирован, когда дата и время найдены в интервале времени.

 CREATE TABLE R
 (
  OID_R     NUMBER NOT NULL,
  Price     INTEGER NOT NULL,
  f         DATE    NOT NULL,
  HourStart DATE    NOT NULL,
  HuorFin   DATE    NOT NULL,
  OID_E     NUMBER          ,
  OID_S     NUMBER          ,
  OID_P     NUMBER NOT NULL
 );

CREATE OR REPLACE TRIGGER TR_D
  BEFORE INSERT OR UPDATE OF OID_R ON R
  FOR EACH ROW
DECLARE
  IntervalR DATE;
  HourStart DATE;
  HourFin   DATE;
BEGIN
  IntervalR := :new.HourFin - :new.HourStart;
  IF IntervalR BETWEEN :old.HourStart AND :old.HourFin THEN
    raise_application_error(-20000, 'Is not avaible');
  END IF;
END;

person MJJS1996    schedule 11.01.2020    source источник
comment
date минус date - это не дата, а количество дней. Итак, IntervalR := :NEW.HourFin - :NEW.HourStart; не может работать, потому что IntervalR - это date. К сожалению, вы не дали полезного описания того, что хотите делать. Поэтому я не могу дать никаких советов, как изменить это, чтобы добиться того, чего вы хотите.   -  person sticky bit    schedule 11.01.2020
comment
Триггер должен быть активирован, когда IntervalR находится между датой HourStart и датой HourFin. Возможно, мне стоит попытаться найти функцию, которая возвращала бы разницу дат не как int, но сохраняла бы временной интервал между этими двумя датами.   -  person MJJS1996    schedule 11.01.2020
comment
Для меня это не имеет смысла. Может быть, вам нужен :new.hourstart >= :old.hourstart AND :new.hourfin <= :old.hourfin. Но кто знает. Может помочь минимальный воспроизводимый пример.   -  person sticky bit    schedule 11.01.2020
comment
@ MJJS1996 дата - это не интервал. Можете ли вы объяснить бизнес-правило, которое хотите применить? HourFin должно быть после HourStart, что-то в этом роде?   -  person William Robertson    schedule 12.01.2020


Ответы (1)


В вашем описании говорится, что «когда datetime находится в интервале времени», тогда вы проверяете, попадает ли разница между новыми значениями между старыми значениями. Это никогда не сработает, но похоже, что реальная проблема, которую вы пытаетесь решить, - это «определить, перекрывают ли новые времена старые или их можно сбросить».
Ваш триггер имеет ряд фундаментальных недостатков, помимо непонимания результата вычитания одной даты из другой. Ваш триггер срабатывает при вставке, но затем использует столбец из старой строки, но при вставке старой строки нет, поэтому все операции с ней приводят к NULL. Следовательно, ваше утверждение IF никогда не может быть правдой. Так что не нужно стрелять по вставке. Триггер также срабатывает при обновлении, но не при любом обновлении. Только при обновлении столбца OID_R. Если OID_R не является столбцом в установленном списке, триггер не срабатывает при обновлении. Также кажется, что OID_R является (или, по крайней мере, должен быть) первичным ключом, в котором он никогда не должен обновляться во время обычных операций. Поэтому никогда не следует запускать обновление. Вы определяете три переменные: одну неверно, а две другие не используются, поэтому ни одна из них не нужна. Мы остаемся с исходным вопросом: перекрывают ли новые времена старые?
Давайте определим допустимые сбросы, когда:

  1. новый конец больше, чем новый старт
  2. текущее время меньше нового старта
  3. текущее время меньше, чем старое время

При этом получаем (учтите, могут быть и другие условия)

create or replace trigger tr_d
  before  update on r
  for each row
begin
   if not (    new.endhour > :new.starthour  
           and sysdate     < :new.starthour
           and sysdate     < :old.starthour
          )
   then 
        raise_application_error(-20000, 'is not avaible');
  end if;
end tr_d;

Остается нерешенным вопрос: «Представляют ли времена значения, повторяющиеся ежедневно (т. Е. Только времена), или указывают время на определенную дату?» Если повторяется ежедневно, вам необходимо удалить день, месяц, год из значений и sysdate.

person Belayer    schedule 13.01.2020