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?

  1. Я не верю, что это сработало, как вы описали в MS SQL Server. Если у вас было ограничение первичного ключа на T_FooBodys.foo_id, тогда вы можете вставить только одну строку с заданным значением.

  2. Делать 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,

Чтобы ответить на данную проблему, я скажу:

  1. Я не знаю о MSSQL, но Oracle строго придерживается внешнего ключа и первичного ключа. Чтобы добавить некоторый внешний ключ, вы должны быть уверены, что этот идентификатор уже существует в первичной таблице. Если этот первичный ключ не существует, вы получите ограничение ORA-xxx нарушено. Подобно внешнему ключу, ограничение первичного ключа должно быть уникальным. Когда что-то не уникальное вставляется в качестве первичного ключа, вы получаете ORA-xxx Первичный ключ нарушен. Я не уверен, что MSSQL так же строг, как Oracle, или нет. Но в MySQL такого рода ситуации можно избежать, используя некоторый механизм, который не является "слишком строгим" (в ограничении внешнего ключа).
  2. Чтобы справиться с этим, вы можете сделать несколько вещей. Во-первых, не смешивайте первичный ключ и внешний ключ в одном поле. Это помогает, когда вы их разделяете. Просто позвольте первичному ключу увеличиваться каждый раз, когда вы вставляете, и убедитесь, что внешний ключ (в другом поле) не нарушает никаких ограничений. Во-вторых, вы можете поддерживать эту концепцию "многофункционального поля", используя только одно поле. Но для этого вам необходимо удалить ограничение первичного ключа из этого многофункционального поля. Следовательно, создайте таблицу без первичного ключа. Я не совсем уверен в этом, так как у меня больше нет доступа к базе данных Oracle. Кто-то, пожалуйста, подтвердите это.
  3. В конце концов, использование отношения 1-1 - это все равно, что доказательство того, что вы неправильно спроектировали структуру таблицы. Потому что, как вы все знаете, 1-1 отношения могут быть упрощены в одну таблицу.

Надеюсь, поможет

RedFilter ответил на вопрос, почему вы получаете ошибку. Мне интересно, почему эти 2 таблицы разделены: похоже, что есть отношение 1 к 1, а заголовок и тело должны быть в основной таблице. Единственная причина, по которой этого нельзя было бы сделать, заключалась в рассмотрении вопроса о производительности.

Другие вопросы по тегам