Oracle не найдены родительские ключи
Связывание исключения со стандартным номером ошибки осуществляется с помощью директивы PRAGMA. Эта директива выполняется во время компиляции, а не во время выполнения. Она определяет, что компилятор должен обработать специфичное для языка условие.
DECLARE
имя_исключения EXCEPTION;
PRAGMAEXCEPTION_INIT (имя_исключения, номер_ошибки);
операторы;
WHEN имя_исключенияTHEN
операторы;
имя_исключения – имя исключения
номер_ошибки – номер стандартной ошибки сервера Oracle
Рассмотрим пример обработки стандартной ошибки сервера Oracle – нарушение целостности. Эта ошибка не является предопределенным исключением, поэтому, прежде чем ссылаться на исключение в секции обработки исключений, необходимо описать это исключение и связать его с номером стандартной ошибки сервера Oracle (-2291 – родительский ключ не найден).
SQL> SELECT * FROM dept;
DEPTNO DNAME LOC
10 ACCOUNTING NEW_YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
2 e_no_dept EXCEPTION;
3 PRAGMA EXCEPTION_INIT (e_no_dept, -2291);
5 INSERT INTO emp (empno, deptno) VALUES (99, 50);
7 WHEN e_no_dept THEN
8 DBMS_OUTPUT.put_line ('Parent key is not found');
9 WHEN OTHERS THEN
10 DBMS_OUTPUT.put_line ('Other error occurred');
Parent key is not found
PL/SQL procedure successfully completed.
Перехват пользовательских исключений
Если Вы хотите обработать ситуацию, которую Вы считаете ошибочной (например, нарушение бизнес-правил), но которая не является ошибкой с точки зрения сервера Oracle, необходимо сначала объявить пользовательское исключение в декларативной секции, вызвать его явно в исполняемой секции и сослаться на исключение в секции обработки исключений.
DECLARE
имя_исключенияEXCEPTION;
RAISE имя_исключения;
WHEN имя_исключенияTHEN
операторы;
Рассмотрим пример. Предположим, на предприятии может быть только один президент. Поэтому при добавлении нового сотрудника необходимо проверять его должность. Если должность нового сотрудника – президент, а на предприятии хотя бы один президент уже есть, необходимо вызвать пользовательское исключение.
SQL> VARIABLE v_job VARCHAR2(20);
SQL> EXECUTE :v_job := 'President'
PL/SQL procedure successfully completed.
2 e_president_exist EXCEPTION;
3 v_count NUMBER;
5 SELECT COUNT(*) INTO v_count FROM emp WHERE LOWER(job)=LOWER(:v_job);
6 IF LOWER(:v_job)='president' AND v_count>0 THEN
7 RAISE e_president_exist;
10 WHEN e_president_exist THEN
11 DBMS_OUTPUT.put_line('President exist already!');
President exist already!
PL/SQL procedure successfully completed.
Обработка исключений во вложенных блоках
Если вложенный блок обрабатывает исключение, он завершается без ошибок и управление передается во внешний блок оператору, следующему за оператором END вложенного блока.
Если в текущем блоке нет обработчика вызванного исключения, исключение распространяется на внешний блок и управление передается подходящему обработчику в секции обработки исключений внешнего блока. При этом операторы, оставшиеся во внешнем блоке, не выполняются. Исключение «поднимается вверх» по вложенным блокам до тех пор, пока не будет найден подходящий обработчик для исключения, вызванного вложенным блоком.
2 v_error_code NUMBER;
3 v_error_text VARCHAR2(100);
4 v_sal emp.sal%TYPE;
6 SELECT sal INTO v_sal FROM emp WHERE LOWER(job)=LOWER(:v_job);
7 DBMS_OUTPUT.put_line('Salary of ' || :v_job || ' is ' || TO_CHAR(v_sal));
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 6
Иногда внутри обработчика исключений выполняются действия, которые сами могут вызвать исключение. Это может привести к бесконечному циклу. Чтобы этого не произошло, обработчик исключений можно заключить в блок и установить для него собственный обработчик исключений, который не должен выполнять никаких действий
EXCEPTION
WHEN OTHERS THEN
операторы;
WHEN OTHERS THEN
2 ответа
Очевидно, у вас есть логическая проблема (круговое рассуждение): вы не можете сначала создать отдел, когда нет сотрудников, потому что ограничение внешнего ключа на CHAIRID не сработает, и вы не можете сначала создать сотрудников, потому что внешний ключ на DEPTID выйдет из строя. И все же ваша модель данных, очевидно, верна.
Одно из решений - не добавлять внешние ключи с самого начала. Сделайте все остальное, вставьте данные и только затем измените таблицы, чтобы добавить внешние ключи.
Лучшее решение - добавить FK с самого начала, но сделать их отложенными и изначально отложенными. Затем вставьте данные и включите ограничения FK. (На самом деле хорошая идея сделать ограничения FK откладываемыми, потому что у вас могут возникнуть аналогичные проблемы в будущем, и вы оцените гибкость.)
Однако лучшее решение - создать таблицы со всеми ограничениями, как и вы. (Тем не менее, сделайте ограничения FK откладываемыми). Затем ВСТАВЬТЕ в ОТДЕЛЫ, но со всем СТУЛЬЕМ, оставшимся NULL . Затем вставьте строки EMPLOYEE и, наконец, ОБНОВИТЕ строки DEPARTMENTS, чтобы отобразить правильный CHAIRID для каждого отдела.
Дело в том, что столбцы FK ДОПУСКАЮТ NULL - воспользуйтесь этим, чтобы разорвать порочный круг (круговая логика).
Теперь - ваше требование состоит в том, чтобы в каждом отделе было ровно одно кресло . вы можете сделать столбец CHAIRID не допускающим значения NULL. Это снова будет мешать описанному мною плану. Добавьте это ограничение (и, конечно, триггер) только после операторов INSERT и UPDATE.
Я обновил свою попытку, сохранив некоторые вещи как CHAR, но по-прежнему получаю аналогичную ошибку: ERROR в строке 1: ORA-02091: откат транзакции ORA-02291: ограничение целостности (MMM1339.ITEMNO_PHAR_FK) нарушено - родительский ключ не найден
Все внешние ключи заявки имеют значения в различных первичных ключах поставки, поэтому я не уверен, почему проблема все еще существует.
Я никогда не слышал о MANDATORY, OR , но похоже, что ваши три таблицы SUPPLIES должны быть одной таблицей со столбцом классификации. Однако меня немного озадачивает классификация - фармацевтическая, хирургическая и нехирургическая. Разве хирургическое и нехирургическое лечение не должно покрывать все? Между прочим, все эти столбцы CHR должны быть VARCHAR2 .
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно.
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей.
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то.
Именованные блоки PL/SQL
Именованные блоки PL/SQL называются программными единицами. Программные единицы делятся на три категории:
§ Процедуры, позволяющие задавать параметры и выполняющие заданные действия
§ Функции, позволяющие задавать параметры, вычисляющие и возвращающие значения
§ Пакеты, объединяющие логически связанные процедуры и функции
Программные единицы подразделяются на хранимые и прикладные подпрограммы (подпрограммы приложения):
исследовал в Ora-02270 и так что вопрос
ошибка ORA-2270 довольно проста: это происходит, когда столбцы, на которые мы ссылаемся во внешнем ключе, не соответствуют первичному ключу или уникальному ограничению в родительской таблице. Распространенными причинами этого являются
- родителю вообще не хватает ограничения
- ограничение родительской таблицы является составным ключом, и мы не ссылались на все столбцы в инструкции внешнего ключа.
не представляется случай в вашей разместил код. Но это отвлекающий маневр, потому что ваш код не работает как вы его разместили. Судя по предыдущим изменениям, я предполагаю, что вы не публикуете свой фактический код, а какой-то упрощенный пример. К сожалению, в процессе упрощения вы устранили все, что вызывает ошибку ORA-2270.
потому что, если мы исправим ваш код, чтобы он работал, он - э - э-работает. Весь путь.
Итак, этот оператор не удался, потому что USER является зарезервированным ключевым словом, и мы не можем имя пользователя таблицы. Давайте исправим это:
и ЛО! Нет ошибки ORA-2270.
Итак, мы мало что можем сделать, чтобы помочь вам дальше. У вас ошибка в коде. Вы можете разместить свой код здесь и один из нас может обнаружить твою ошибку. Или вы можете проверить свой код и открыть его для себя.
тип данных в таблице заданий (Varchar2 (20)) не соответствует типу данных в таблице пользователей (число не равно нулю).
удалит все задания с несуществующими пользователями. Вы можете перенести их в копию этой таблицы, которая будет содержать архивные данные.
скорее всего, когда у вас отсутствует первичный ключ не определен из родительской таблицы. затем это происходит.
Как добавить первичный ключ в parent, как показано ниже:
надеюсь, это сработает.
в моем случае проблема была вызвана инвалида ПК.
для того, чтобы включить его:
Я ищу имя ограничения с:
SELECT * FROM USER_CONS_COLUMNS WHERE TABLE_NAME = 'referenced_table_name';
затем я взял имя ограничения, чтобы включить его со следующей командой:
ALTER TABLE table_name ENABLE CONSTRAINT constraint_name;
я столкнулся с той же проблемой в моем сценарии, как показано ниже:
Я создал таблицу учебников сначала с
затем столе главы:
create table chapter(txtbk_isbn varchar2(13),chapter_title varchar2(40), constraint pk_chapter primary key(txtbk_isbn,chapter_title), constraint chapter_txtbook foreign key (txtbk_isbn) references textbook (txtbk_isbn));
затем темы стол:
теперь, когда я хотел создать отношение под названием chapter_topic между главой (с составным первичным ключом) и темой (с одним первичным ключом столбца), я столкнулся с проблемой со следующим запросом:
create table chapter_topic(txtbk_isbn varchar2(13),chapter_title varchar2(40),topic_id varchar2(20), primary key (txtbk_isbn, chapter_title, topic_id), foreign key (txtbk_isbn) references textbook(txtbk_isbn), foreign key (chapter_title) references chapter(chapter_title), foreign key (topic_id) references topic (topic_id));
решение должен был ссылаться на составной внешний ключ, как показано ниже:
create table chapter_topic(txtbk_isbn varchar2(13),chapter_title varchar2(40),topic_id varchar2(20), primary key (txtbk_isbn, chapter_title, topic_id), foreign key (txtbk_isbn, chapter_title) references chapter(txtbk_isbn, chapter_title), foreign key (topic_id) references topic (topic_id));
общие причины для этого являются
- у родителя вообще отсутствует ограничение
- ограничение родительской таблицы является составным ключом, и мы не ссылались на все столбцы в инструкции внешнего ключа.
- указанное ограничение PK существует, но отключено
So idisble the constraint from table B.
AFter that i delete the rows from table A and reserted some other rows.
But now when i try to enable the constraint,I am getting this error.
ORA-02291: integrity constraint (string.string) violated - parent key not found.
How to overcome this situation?
Ответы 4
нам нужны некоторые перестановки, чтобы подавить ошибку ORA-02291:
- Прежде всего, операторы ВСТАВЛЯТЬ должны заканчиваться полуколоны.
- Должна существовать таблица с именем ПОСТАВЩИК, на которую можно ссылаться.
Создавайте таблицы без ИНОСТРАННЫЕ КЛЮЧИ, и после того, как они все созданы, Таблицы ИЗМЕНИТЬ для включения ИНОСТРАННЫЕ КЛЮЧИ. Чтобы подавить несогласованность данных во время операций INSERT, нам нужно создать ИНОСТРАННЫЕ КЛЮЧИ как ОТЛОЖЕННЫЙ ПЕРВОНАЧАЛЬНО ОТЛОЖЕН (следующим образом мы не столкнемся с какой-либо ошибкой, даже если выдается окончание COMMIT).
Я думаю, вам лучше хранить столбцы ПОСТАВЩИК НЕТ как INT (ЭГЕР) или НОМЕР, а не СИМВОЛ. Кроме того, тип данных СИМВОЛ устарел, их лучше преобразовать в VARCHAR2.
Итак, используйте следующую серию действий (в нижней части я изменил некоторые значения РЕКВИЗИЦИЯ, чтобы не нарушать Внешние ограничения):
Спасибо за все подробности. Не могли бы вы прокомментировать таблицу заявок, с которой у меня возникла проблема? Для каждой поставки у них может быть много заявок, что означает, что слабой сущностью, которая содержит FK, является заявка, и я чувствую, что мои обновления заявки без наличия PK в 2 из 3 таблиц ресурсов все равно будут вызывать ошибку. Если DEFERRABLE исправит это, не могли бы вы помочь мне понять, как?
@MarkMcGown милости прошу, я отредактировал ответ друг.
Объедините SUPPLIES_SURGICAL и SUPPLIES_NONSURGICAL как одну таблицу SUPPLIES и определите PHARMA_DOSAGE как дочернюю таблицу под ней.
Теперь строки SUPPLIES должны быть либо хирургическими, либо нет, что может быть реализовано как флаг Y / N и обеспечено проверочным ограничением. (Однако одна из возможных проблем заключается в том, что модель не мешает вам добавлять дозировку для хирургического инструмента.)
Далее я сделал ITEMNO целым числом и исправил ваши столбцы CHAR . Вы можете рассмотреть возможность проверки типов данных для всех столбцов, оканчивающихся на NO , особенно если они будут генерироваться последовательно. Я бы также сделал все сгенерированные столбцы идентификаторов столбцов PK, но детали оставлю на ваше усмотрение.
Очень ценю эту версию, Уильям. Проблема в том, что моя реляционная модель требует, чтобы у меня было несколько внешних ключей.
Не уверен, что вы подразумеваете под своей реляционной моделью или с какими конструктивными ограничениями вы сталкиваетесь. Мое предложение состоит в изменении вашей модели данных.
К сожалению (для вашего кода DDL) я должен согласиться с @William Robertson - вам нужно изменить свою модель, и, следовательно, вам нужно полностью переработать свой код DDL. Причины этого следующие:
Глядя на реконструированную модель из исходного кода DDL, мы видим, что REQUISITION имеет 3 (извините, 4) родительские таблицы. Вот почему его вставки всегда терпят неудачу из-за нарушений внешнего ключа. Ваша модель:
Упрощенный пример, иллюстрирующий проблему в виде кода DDL, может выглядеть примерно так:
Итак, когда наши родительские таблицы заполнены, просто проверьте:
Все хорошо. Теперь мы хотим вставить несколько строк в нашу дочернюю таблицу.
Вы видите, что правильная родительская таблица не просто «выбирается автоматически».
В модели OTOH Уильяма REQUISITION имеет только одну родительскую (таблицу) в отношении «поставок». Это должно значительно упростить вставку строк . см. Ниже.
Этот ответ относится к вашему вопросу о том, почему ваше обновленное определение с отложенными ограничениями по-прежнему дает нарушение FK.
После вставки строк, но до попытки фиксации:
Элемент 888520 нарушает ограничение ITEMNO_PHAR_FK , потому что он не определен в родительской таблице SUPPLIES_PHARMACEUTICAL :
Это также нарушает ITEMNO_SURG_FK , потому что 888520 не находится в родительской таблице SUPPLIES_SURGICAL :
И так далее. Каждая строка заявки нарушает два ограничения. Определение ограничений как отложенных ничего не меняет, кроме времени возникновения ошибки.
Чтобы удовлетворить ваши определения FK, каждый номер элемента должен присутствовать во всех трех таблицах ресурсов.
Если вам действительно нужно иметь три таблицы ресурсов, вам понадобятся три отдельных столбца предметов снабжения, каждый со своим собственным FK для соответствующей таблицы.
(И вам действительно следует изменить эти столбцы CHAR на стандартный строковый тип. CHAR не имеет места в базе данных Oracle, это чисто из-за странной переносимости и требований полноты ANSI, а не типа, который вы фактически должны использовать.)
Функции для перехвата ошибок
Для обработки всех ошибок, которые не были перехвачены обработчиками исключений, используется предложение WHEN OTHERS. Обработчик WHEN OTHERS может быть только один и всегда располагается после всех других обработчиков исключений. Чтобы определить, какое именно исключение перехвачено обработчиком исключений, можно использовать две функции:
· SQLCODE – возвращает числовое значение кода ошибки
- 0 – исключений не было
- 1 – пользовательское исключение
- +100 – исключение NO_DATA_FOUND
- отрицательное целое – номер ошибки сервера Oracle
Почти все коды исключений сервера Oracle имеют отрицательное значение, кроме NO_DATA_FOUND, код которого +100. Это происходит потому, что в соответствии со стандартом ANSI, если строка не найдена значение SQLCODE должно быть равно +100.
SQL> VARIABLE v_job VARCHAR2(20);
SQL> EXECUTE :v_job := 'Engineer'
PL/SQL procedure successfully completed.
2 v_error_code NUMBER;
3 v_error_text VARCHAR2(100);
4 v_sal emp.sal%TYPE;
6 SELECT sal INTO v_sal FROM emp WHERE LOWER(job)=LOWER(:v_job);
7 DBMS_OUTPUT.put_line('Salary of ' || :v_job || ' is ' || TO_CHAR(v_sal));
9 WHEN OTHERS THEN
10 v_error_code := SQLCODE;
11 v_error_text := SQLERRM;
12 DBMS_OUTPUT.put_line(TO_CHAR(v_error_code) || ' - ' || v_error_text);
100 - ORA-01403: no data found
PL/SQL procedure successfully completed.
Answers
Error: ORA 2291
Text: integrity constraint (%s.%s) violated - parent key not found
-------------------------------------------------------------------------------
Cause: Attempted to insert or update values that do not have corresponding
Parent key values.
Action: obvious.
Explanation:
If you have a FOREIGN KEY constraint on a table you cannot INSERT
or UPDATE rows such that they would not have a matching PARENT
in the MASTER table.
>
Refer to metalink Doc ID: Note:19524.1
Yes you are getting the correct error .
If Oracle allows you to do this that is allow you to insert into the foreign key column without corresponding primary key then What is the purpose of enforcing primary and foreign key or parent child relationship.
In your case you can only insert into the foreign key if you have the corresponding entry in the Primary key.
If at the time of creating foreignn key, you have use "On delete cascade or On delete set null" Then you can simply delete the primary key without doping anything to the foreign key. Corresposnding values for the foreignn key will automatically be deleted or set to null.
When you enable the constraint it check existing data also. so overcome from this situation enable the constraint with novalidate option so it check for future insertion only not check existing data.
Edited by: Vivekdhiman on Oct 21, 2008 12:12 PM
The correct answer is to ensure that you DO have the parent key values -- ie in the Parent table.
You would use NOVALIDATE only under exceptional circumstances -- eg you are "fixing" data which was erroneous OR that you need to ignore existing rows but want the constraint enabled for future rows to be inserted after this point in time.
I have a table A which has a column x as primary key.
This column x is referenced in column y of table B.
Now as per my understanding,table A is the primary table and table B is the foriengn key table.
On deleteing from table A,i got the error child record found as x is foreign key in table B.
I disabled the foriegn key constraint in table B.
I deleted the rows from table A.
I,then reserted some rows in tbale A.
I committed the transaction.
Now I want to enable the foriegn key constraint in table B.
But I am getting parent key not found.
I have records in parent table ie table A. I am not inserting in table B[foreign key table].
I inserted in table A.
The situation is like this.
table A table B
x y
1 1
2 1
3 2
4 3
5
6
7
8
Now when i enable cforiegn key constraint in table B,I get parent key not found,but all the parent key is present in table A.
I inserted 5,6,7,8 in table A after deleting some records.
Edited by: MYH on Oct 21, 2008 12:33 AM
SQL> create table parent1(id number primary key);
SQL> insert into parent1 values(&i);
Enter value for i: 1
old 1: insert into parent1 values(&i)
new 1: insert into parent1 values(1)
SQL> /
Enter value for i: 2
old 1: insert into parent1 values(&i)
new 1: insert into parent1 values(2)
SQL> /
Enter value for i: 3
old 1: insert into parent1 values(&i)
new 1: insert into parent1 values(3)
SQL> /
Enter value for i: 4
old 1: insert into parent1 values(&i)
new 1: insert into parent1 values(4)
SQL> create table child1(id number CONSTRAINT FK_ID references parent1(id));
SQL> insert into child1 values(&i);
Enter value for i: 1
old 1: insert into child1 values(&i)
new 1: insert into child1 values(1)
SQL> /
Enter value for i: 1
old 1: insert into child1 values(&i)
new 1: insert into child1 values(1)
SQL> /
Enter value for i: 3
old 1: insert into child1 values(&i)
new 1: insert into child1 values(3)
SQL> /
Enter value for i: 2
old 1: insert into child1 values(&i)
new 1: insert into child1 values(2)
SQL> /
Enter value for i: 4
old 1: insert into child1 values(&i)
new 1: insert into child1 values(4)
SQL> select * from parent1;
SQL> delete from parent1 where > delete from parent1 where > *
ERROR at line 1:
ORA-02292: integrity constraint (SCOTT.FK_ID) violated - child record found
SQL> select constraint_name,constraint_type from user_constraints where table_name='CHILD
SQL> ALTER TABLE CHILD1 DISABLE CONSTRAINT FK_ID;
SQL> delete from parent1 where row deleted.
SQL> ALTER TABLE CHILD1 ENABLE CONSTRAINT FK_ID;
ALTER TABLE CHILD1 ENABLE CONSTRAINT FK_ID
*
ERROR at line 1:
ORA-02298: cannot validate (SCOTT.FK_ID) - parent keys not found
Итак, первоначальный вопрос, который мне было предложено решить, заключался в следующем:
Создайте две таблицы: Сотрудник: empID (PK), empFname, empLname, deptID (FK) и Отдел: deptID (PK), deptName, ChairID. ChairID - это empID из таблицы сотрудников. Вставьте не менее 3 строк в таблицу «Отдел» и не менее 6 строк в таблицу «Сотрудник». Создайте триггер при обновлении ChairID, который применяет следующие бизнес-правила: Один сотрудник может возглавлять не более одного отдела. В каждом отделе ровно одно кресло.
Мое решение проблемы было таким:
Обе мои таблицы создают и запускают компиляцию, но при попытке вставить в мои таблицы все мои операторы вставки попадают:
Ошибка SQL: ORA-02291: ограничение целостности (SYSTEM.SYS_C0010675) нарушено - родительский ключ не найден 02291. 00000 - «ограничение целостности (% s.% S) нарушено - родительский ключ не найден» * Причина: значение внешнего ключа не имеет соответствует значению первичного ключа. * Действие: удалите внешний ключ или добавьте соответствующий первичный ключ.
Помимо логических трудностей, которые законны и интересны, в ваших утверждениях есть и другие ошибки. Посмотрите на номера отделов в INSERT для сотрудников, это 301, 302, 303 . но номера ваших отделов в таблице DEPARTMENTS - 401, 402, 403 . Как это должно работать? И посмотрите также в другую сторону, ваши сотрудники - 1001, 1002, . поэтому CHAIRID не может быть 301, 302, 303 - это должен быть идентификатор реального сотрудника в таблице EMPLOYEES!
Читайте также: