2015-12-01 1 views
0

Мое требование - написать процедуру для добавления значений в таблицу СТРАН. Но сначала нужно проверить, существуют ли соответствующие значения в другой таблице, REGIONS, поскольку это внешний ключ. Только в том случае, если существуют значения, это допустимая вставка в таблицу СТРАН. В противном случае нет.Процедура проверки несуществующих значений в внешней таблице oracle

я написал кусок кода, но он бросает кучу ошибок:

ORA-00950 отсутствует ключевое слово PLS-00103 Встречающиеся символ ТОГДА, когда ожидает одно из следующих действий: (начало случае объявить, и исключение выхода) (переменные связывания) (продолжение закрыть текущий удалить выборки замка)

Я написал этот код:

CREATE OR REPLACE PROCEDURE addi1 (c_cntry_id IN OUT COUNTRIES.COUNTRY_ID%TYPE, 
             c_cntr_name IN COUNTRIES.COUNTRY_NAME%TYPE, 
             c_rgn_id IN COUNTRIES.REGION_ID%TYPE) 
IS 
l_exst number(1); 

begin 
    select case 
      when exists 
( select r.region_id from regions r where r.region_id IN 
(SELECT REGION_ID from regions) 

         ); 
      then 1 
      else 0 
     end into l_exst 


    if l_exst = 1 
    then 
    INSERT INTO countries(COUNTRY_ID, COUNTRY_NAME,REGION_ID) 
    values (c_cntry_id, c_cntr_name,c_rgn_id); 
    else 
    DBMS_OUTPUT.put_line('YOU CANNOT'); 
    end if; 
end; 
/

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

ответ

1

Это неправильный способ принудительного применения внешнего ключа. Он не работает в многопользовательской среде, потому что мы не можем видеть, что делают другие пользователи в своих незанятых сеансах. Поэтому, возможно, ваш код найдет РЕГИОН, когда какой-либо другой пользователь собирается совершить удаление, или, наоборот, ваш код может не найти REGION, а кто-то еще собирается совершить вставку.

Гораздо лучше оставить его встроенным функциям Oracle.

  1. Определить (и включить!) Фактическое ограничение внешнего ключа между РЕГИОНОМ и СТРАНАМИ.
  2. Просто введите таблицу СТРАН.
  3. Обработать нарушения внешнего ключа в блоке Исключения.

Это решение использует PRAGMA EXCEPTION_INIT, чтобы определить конкретное исключение для этой цели. Find out more.

create or replace procedure addi1 (c_cntry_id in out countries.country_id%type, 
             c_cntr_name in countries.country_name%type, 
             c_rgn_id in countries.region_id%type) 
is 
    region_not_found exception; 
    pragma exception_init(region_not_found, -2291); 
begin 
    insert into countries(country_id, country_name,region_id) 
    values (c_cntry_id, c_cntr_name,c_rgn_id); 
exception 
    when region_not_found then 
     dbms_output.put_line(c_rgn_id||' is not a valid REGION id'); 
     raise; 
end addi1; 
/

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


Для полноты здесь приведен синтаксис для проверки существования записи.

create or replace procedure addi1 (c_cntry_id in out countries.country_id%type, 
             c_cntr_name in countries.country_name%type, 
             c_rgn_id in countries.region_id%type) 
is 
    region_exists pls_integer; 
begin 
    begin 
     select 1 into region_exists 
     from regions r 
     where r.region_id = c_rgn_id; 
    exception 
     when no_data_found then 
      region_exists := 0; 
    end; 
    if region_exists = 1 then 
     ... 

Но, как я уже сказал, не делайте этого.


"он дал мне ORA-00001"

Так ясно вы уже определили запись СТРАНАМИ с идентификатором 'Ff'. Если вы хотите обработать исключение чисто вы можете использовать предопределенное исключение DUP_VAL_ON_INDEX:

 when DUP_VAL_ON_INDEX then 
     dbms_output.put_line('There is an existing COUNTRIES record with an ID of' || c_cntry_id); 

В реальной жизни мы всегда должны вызывать исключение: это прерогатива вызывающей программы, чтобы решить, насколько серьезна ошибка.Но не стесняйтесь подавлять ошибки, если хотите.

+0

спасибо, я выполнил вашу первую процедуру, и когда я ее выполнил, она дала мне ORA-00001 (единственное ограничение ключа). Теперь я не хочу исключений ORA. Только те, которые я определил (region_not_found exception). Я выполняю процедуру следующим образом: DECLARE outputValue CHAR (2): = 'Ff'; начало addi1 (outputValue, 'JustKii', 5); конец; / – user3400060

0

Просто ответить на ваш вопрос синтаксиса:

Вы всегда выбрать из чего-то. В вашем запросе отсутствует, и есть; в середине его.

select case 
      when exists (select r.region_id 
        from regions r 
        where r.region_id in (select region_id 
              from regions) 

        ) then 
       1 
      else 
       0 
      end 
    into l_exst 
    from dual; 

Существует что-то странное с этой части запроса:

select r.region_id 
from regions r 
where r.region_id in (select region_id 
         from regions) 

Как вы думаете, в частности, необходимо?

+0

Да, иначе, как я узнаю, существует ли region_id в таблице регионов? – user3400060