1->1/1->N отношения в Oracle?
У меня 2 стола
T_Foo
foo_id
fooHeader
T_FooBodys
foo_id
foobody
foo_id - это первичный ключ для обеих соответствующих таблиц. Во второй таблице foo_id - это внешний ключ первой таблицы. Я генерирую PK для обоих значений таблицы, используя последовательность, и пытаюсь сделать вставку - один раз в FooHeader и дважды в FooBody.
Мой код падает при второй вставке в t_FooBodys в цикле из-за ошибки "ORA-00001: нарушение уникального ограничения (USERID.FooBodys_PK)"
Итак, у меня есть 2 вопроса:
1) В чем здесь принципиальная разница между MSSQL Server и Oracle? Это отлично работало в SQL Server! У меня были отношения один к одному / много все время там
2) Как проще всего это исправить, кроме добавления еще одного ключа и, по сути, прекращения концепции общего первичного ключа?
Большое спасибо
6 ответов
foo_id - это первичный ключ для обеих соответствующих таблиц
У вас не может быть повторяющихся записей для ПК с MS SQL Server или Oracle, поэтому вы где-то допустили ошибку. Возможно, вы установили отношение FK в SQL Server, но вы не можете установить foo_id
в T_FooBodys
как PK, и это все еще позволило дублировать записи.
Если foo_id является первичным ключом в таблице T_FooBodys, то он должен быть уникальным. Похоже, вы хотите, чтобы foo_id был внешним ключом в T_FooBodys. Я думаю, что SQL Server имеет такое же ограничение - первичный ключ должен быть уникальным - это в основном определение первичного ключа.
Можете ли вы добавить новый ПК в таблицу Bodys? И оставить foo_id как PK в таблице Header и внешний ключ в таблице Bodys?
Я не верю, что это сработало, как вы описали в MS SQL Server. Если у вас было ограничение первичного ключа на
T_FooBodys.foo_id
, тогда вы можете вставить только одну строку с заданным значением.Делать
T_FooBodys
принять несколько строк для данного значенияfoo_id
, вы должны добавить еще один столбец и сделать первичный ключ из двух столбцов надfoo_id
с этим новым столбцом. Это позволит вам иметь различные значения во втором столбце, сохраняя уникальность.CREATE TABLE T_FooBodys ( foo_id INTEGER NOT NULL, foo_body_id INTEGER NOT NULL, foobody TEXT, PRIMARY KEY (foo_id, foo_body_id), FOREIGN KEY (foo_id) REFERENCES T_Foo (foo_id) );
Вы должны изменить таблицу T_FOOBODYS
следующим образом:
/*Create table*/
create table T_FOOBODYS
(
FOOBODY_ID NUMBER(10) not null,
FOO_ID NUMBER(10) not null,
FOOBODY VARCHAR2(512)
);
/* Create/Recreate primary, unique and foreign key constraints */
alter table FOOBODY
add constraint FBPK primary key (FOOBODY_ID)
ENABLE;
alter table FOOBODY
add constraint FBFK foreign key (FOO_ID)
references T_FOO(FOO_ID);
Вот, FOOBODY_ID
обозначает ваш первичный ключ для вашего T_FOOBODYS
стол и FOO_ID
является ссылочным ограничением для T_FOO
,
Чтобы ответить на данную проблему, я скажу:
- Я не знаю о MSSQL, но Oracle строго придерживается внешнего ключа и первичного ключа. Чтобы добавить некоторый внешний ключ, вы должны быть уверены, что этот идентификатор уже существует в первичной таблице. Если этот первичный ключ не существует, вы получите ограничение ORA-xxx нарушено. Подобно внешнему ключу, ограничение первичного ключа должно быть уникальным. Когда что-то не уникальное вставляется в качестве первичного ключа, вы получаете ORA-xxx Первичный ключ нарушен. Я не уверен, что MSSQL так же строг, как Oracle, или нет. Но в MySQL такого рода ситуации можно избежать, используя некоторый механизм, который не является "слишком строгим" (в ограничении внешнего ключа).
- Чтобы справиться с этим, вы можете сделать несколько вещей. Во-первых, не смешивайте первичный ключ и внешний ключ в одном поле. Это помогает, когда вы их разделяете. Просто позвольте первичному ключу увеличиваться каждый раз, когда вы вставляете, и убедитесь, что внешний ключ (в другом поле) не нарушает никаких ограничений. Во-вторых, вы можете поддерживать эту концепцию "многофункционального поля", используя только одно поле. Но для этого вам необходимо удалить ограничение первичного ключа из этого многофункционального поля. Следовательно, создайте таблицу без первичного ключа. Я не совсем уверен в этом, так как у меня больше нет доступа к базе данных Oracle. Кто-то, пожалуйста, подтвердите это.
- В конце концов, использование отношения 1-1 - это все равно, что доказательство того, что вы неправильно спроектировали структуру таблицы. Потому что, как вы все знаете, 1-1 отношения могут быть упрощены в одну таблицу.
Надеюсь, поможет
RedFilter ответил на вопрос, почему вы получаете ошибку. Мне интересно, почему эти 2 таблицы разделены: похоже, что есть отношение 1 к 1, а заголовок и тело должны быть в основной таблице. Единственная причина, по которой этого нельзя было бы сделать, заключалась в рассмотрении вопроса о производительности.