Проблема внешнего ключа в SQL - PullRequest
1 голос
/ 17 февраля 2011

Я просто хочу спросить, потому что я создал таблицу со столбцом с двумя первичными ключами, как показано ниже:

CREATE TABLE Parent(
Mother varchar(50) NOT NULL,
Father varchar(50) NOT NULL,
PRIMARY KEY(Mother, Father),
Organization varchar(50) NOT NULL
);

Затем я пытаюсь создать другую таблицу, которая будет иметь внешний ключ для показанной таблицывыше:

CREATE TABLE Child(
Name varchar(50) NOT NULL PRIMARY KEY,
Child_Mother varchar(50) REFERENCES Parent(Mother),
Child_Father varchar(50) REFERENCES Parent(Father),
Sibling varchar(50) NOT NULL
);

Поэтому я в основном пытаюсь ссылаться на два столбца в дочерней таблице на один столбец из родительской таблицы с двумя первичными ключами.Это вообще возможно?Большое спасибо!:)

* Только образцы таблиц.Но на самом деле похожи на это.

Ответы [ 3 ]

4 голосов
/ 17 февраля 2011

Вы не создали «таблицу со столбцом с двумя первичными ключами», вы создали одну таблицу с одним составным первичным ключом.

И то, что вы делаете, действительно возможно, но не вкак вы это делаете.

Проблема в том, что у вас может быть две Parent строки с одинаковыми Mother и разными Father.Но для связи с внешним ключом на Child_Mother потребуется один экземпляр Mother в таблице Parent, в противном случае он не будет знать, к какой строке он относится.

Вы можетелибо в дочернем элементе есть объединенный столбец, который ссылается на объединенный первичный ключ, либо он может разделять строки Parent.

Таким образом, я имею в виду, что в родительскую таблицу обычно не помещаются два человека.в одной строке обычно на одного человека приходится по одной строке, и ребенок просто ссылается на две отдельные строки в таблице Parent, одну для матери и одну для отца.


В терминахиз ваших фактических таблиц:

create table Subject(
    Subject_ID varchar(50) NOT NULL,
    Subject_Description varchar(50) NOT NULL,
    PRIMARY KEY(Subject_ID, Subject_Description),
    Subject_SID int references Student(Student_ID),
    Unit varchar(50) NOT NULL
)

Это на самом деле не нормализовано, поскольку описание субъекта почти неизменно, зависит от идентификатора субъекта.Я думаю, что первичный ключ, вероятно, должен быть только на предмете ID.Конечно, есть еще индекс в описании темы, но он не должен быть частью первичного ключа.

Я все еще не уверен, что вы понимаете, о чем я говорю, поэтому я 'попробую уточнить.Строка:

PRIMARY KEY(Subject_ID, Subject_Description)

делает не двумя первичными ключами, она составляет один первичный ключ, состоящий из двух столбцов (идентификатор и описание).По этой причине возможно иметь две строки с одинаковым идентификатором при условии, что описание отличается.

Таким образом, ссылка внешнего ключа на столбец идентификатора невозможна .Допустим, у вас было две строки:

ID  Subject  Other
--  -------  ---------
 7  Maths    blah blah
 7  Physics  yada yada

, а затем попытался добавить в таблицу расписаний строку с Schedule_SID, установленным на 7. Это задохнется, потому что СУБД не будет знать , которая 7, на который вы ссылаетесь.Так что он даже не должен позволять вам устанавливать это ограничение внешнего ключа, потому что целевой столбец не уникален.

1 голос
/ 17 февраля 2011

Попробуйте это -

CREATE TABLE Child(
    Name varchar(50) NOT NULL PRIMARY KEY,
    Child_Mother varchar(50),
    Child_Father varchar(50),
    Sibling varchar(50) NOT NULL,
    Foreign Key (Child_Mother, Child_Father) references Parent(Mother, Father)
);

Поскольку вы создаете первичный ключ, состоящий из двух столбцов, вам нужно ссылаться на них вместе.

То, что сказал Паксдиабло, верно. Вы создаете составной первичный ключ, который состоит из двух столбцов. Я бы предложил вам использовать Суррогатный первичный ключ .

Редактировать

CREATE TABLE Child(
    id bigint NOT NULL auto_increment,  // an "id" column
    Name varchar(50) NOT NULL unique,
    age int not null,
    primary key (id)    // "id" column is being declared as surrogate primary key
);

Второе редактирование

create table Subject(

    id int not null,
    Subject_ID varchar(50) NOT NULL,
    Subject_Description varchar(50) NOT NULL,
    PRIMARY KEY(id),
    Subject_SID int references Student(Student_ID),
    Unit varchar(50) NOT NULL
);

ALTER TABLE Subject ADD CONSTRAINT subject_unique UNIQUE (Subject_id, Subject_Description);

create table Schedule(
    Day_MTWTHF varchar(50) NOT NULL,
    TIME_HH varchar(50) NOT NULL,
    subject_id int not null,                   -- my newly added column
    Schedule_SID int references Student(Student_ID),
    foreign key(subject_id) references Subject(id)
);
0 голосов
/ 17 февраля 2011

Я бы сказал, что ваш выбор первичного ключа плох для родительской таблицы.Похоже, вы используете имена.Что произойдет, если у вас есть две отдельные пары, чьи имена совпадают?Джон и Джейн Смит с Алисой и Бобом для детей, по вашему замыслу, также будут теми же Джоном и Джейн Смит из соседнего города, у которых есть Чарли и Долорес для детей, хотя на самом деле они совершенно не связаны.

Имена всегда являются плохим выбором для ключей, так как имена могут повторяться.Использование чего-то, что гарантированно будет уникальным, например, автоинкрементное целое число, будет намного безопаснее и позволит вам отделить J & J Smith от Springfield от J & J Smith от Shelbyville.

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