Сравнение дат с таблицей ": new" в SQL - PullRequest
0 голосов
/ 19 января 2012

Я новичок в SQL, поэтому терпите меня.

Я пытаюсь создать триггер в SQL.Этот код доставляет мне проблемы:

select brw.borage, bt.agelower, bt.ageupper 
into borage, minage, maxage
from borrower brw
  inner join loan ln on ln.borid = brw.borid
  inner join bookcopy bc on ln.bcid = bc.bcid
  inner join booktitle bt on bt.isbn = bc.isbn
where ln.bcid = :new.bcid
and ln.borid = :new.borid;
-- and ln.dateout = :new.dateout;

Первичный ключ в таблице ссуд состоит из "bcID", "borID" и "dateOut".Когда я закомментирую последнюю строку, я получаю только что добавленные строки в таблицу.С последней строкой без комментариев, она не будет работать!

Я просто получаю эту ошибку (со строкой без комментария):

Row 34: ORA-01403: no data found
ORA-01403: no data found

означает, что оракул не нашел ни одной строки, соответствующей критериям запроса.

ПРИМЕЧАНИЕ.раскомментируйте строку, я также удаляю точку с запятой над ней.

Ответы [ 2 ]

4 голосов
/ 19 января 2012

OK. Во-первых, триггер уровня строки в таблице A не должен запрашивать таблицу A. В общем случае это приведет к ошибке «ORA-04091: таблица мутирует». Поскольку ваш триггер определен для LOAN, запрос не должен ссылаться на таблицу LOAN. Он должен ссылаться только на данные для текущей строки в записи :NEW.

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

select brw.borage
  into borage
  from borrower brw
 where brw.borid = :new.borid;

select bt.agelower, bt.ageupper 
  into minage, maxage
  from bookcopy bc on :new.bcid = bc.bcid
       inner join booktitle bt on bt.isbn = bc.isbn;

Вы можете объединить два запроса, но я не вижу простого способа сделать это, не сделав результат более сложным, чем вы, вероятно, хотите.

Кроме того, вы действительно хотите избежать использования локальных переменных, которые разделяют имя столбца в вашей базе данных (например, borage). Это приводит к довольно странным ошибкам при разрешении области видимости. Например, используя таблицу SCOTT.EMP

Нет сотрудников с EMPNO из -17

SQL> select count(*)
  2    from emp
  3   where empno = -17;

  COUNT(*)
----------
         0

Но когда я пишу простой блок PL / SQL, который пытается подсчитать количество сотрудников с EMPNO из -17, я получаю результат 14. Вы можете обнаружить ошибку?

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    empno integer := -17;
  3    cnt   integer;
  4  begin
  5    select count(*)
  6      into cnt
  7      from emp e
  8     where e.empno = empno;
  9    dbms_output.put_line( cnt );
 10* end;
SQL> /
14

PL/SQL procedure successfully completed.

Проблема в том, что когда я писал e.empno = empno, я явно хотел, чтобы левая часть выражения ссылалась на столбец EMPNO в таблице EMP, а правая часть выражения - на локальная переменная EMPNO. К сожалению для меня, однако, Oracle разрешает неквалифицированный EMPNO сначала в столбец таблицы, а затем - в локальную переменную с тем же именем. Если вы используете именованные блоки PL / SQL, вы можете обойти это, используя имя блока в качестве псевдонима для локальной переменной, но практически никто этого не делает.

Вместо этого, чтобы избежать подобных проблем, большинство разработчиков будут использовать какой-то особенный префикс для имен переменных. Например, я использую P_ в качестве префикса для имен параметров, L_ в качестве префикса для локальных переменных и G_ в качестве префикса для глобальных переменных пакета. Это довольно распространенное соглашение, но существуют и другие соглашения. Важно просто иметь какой-то способ гарантировать, что у вас никогда не будет локальной переменной и имени столбца, использующего одно и то же имя.

0 голосов
/ 19 января 2012

Если вам нужно игнорировать эту ошибку и продолжить выполнение триггера, вы можете просто добавить

exception
  WHEN NO_DATA_FOUND THEN
  NULL

так что тело вашего триггера выглядит как

begin
   select brw.borage, bt.agelower, bt.ageupper 
   into borage, minage, maxage
   from borrower brw
   inner join loan ln on ln.borid = brw.borid
   inner join bookcopy bc on ln.bcid = bc.bcid
   inner join booktitle bt on bt.isbn = bc.isbn
   where ln.bcid = :new.bcid
   and ln.borid = :new.borid;
   and ln.dateout = :new.dateout;
   // other actions

   exception
   WHEN NO_DATA_FOUND THEN
   NULL
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...