253 votes

Comment créer une clé étrangère dans SQL Server?

Je n'ai jamais "codé à la main" le code de création d'objet pour SQL Server et la décomposition de clé étrangère est apparemment différente entre SQL Server et Postgres. Voici mon sql jusqu'ici:

 drop table exams;
drop table question_bank;
drop table anwser_bank;

create table exams
(
    exam_id uniqueidentifier primary key,
    exam_name varchar(50),
);
create table question_bank
(
    question_id uniqueidentifier primary key,
    question_exam_id uniqueidentifier not null,
    question_text varchar(1024) not null,
    question_point_value decimal,
    constraint question_exam_id foreign key references exams(exam_id)
);
create table anwser_bank
(
    anwser_id           uniqueidentifier primary key,
    anwser_question_id  uniqueidentifier,
    anwser_text         varchar(1024),
    anwser_is_correct   bit
);
 

Lorsque je lance la requête, j'obtiens cette erreur:

Msg 8139, Niveau 16, État 0, Ligne 9 Le nombre de colonnes faisant référence à une clé étrangère diffère du nombre de colonnes référencées, la table 'question_bank'.

Pouvez-vous repérer l'erreur?

337voto

AlexCuse Points 9823

Et si vous voulez simplement créer la contrainte seule, vous pouvez utiliser ALTER TABLE

 alter table MyTable
add constraint MyTable_MyColumn_FK FOREIGN KEY ( MyColumn ) references MyOtherTable(PKColumn)
 

Je ne recommanderais pas la syntaxe mentionnée par Sara Chipps pour la création en ligne, simplement parce que je préfère nommer mes propres contraintes.

204voto

John Boker Points 36308
create table question_bank
(
    question_id uniqueidentifier primary key,
    question_exam_id uniqueidentifier not null,
    question_text varchar(1024) not null,
    question_point_value decimal,
    foreign key ( question_exam_id ) references exams (exam_id)
);

70voto

Sara Chipps Points 4391

Vous pouvez également nommer votre contrainte de clé étrangère en utilisant:

 CONSTRAINT your_name_here FOREIGN KEY (question_exam_id) REFERENCES EXAMS (exam_id)
 

32voto

Shavais Points 366

J'aime AlexCuse réponse, mais quelque chose que vous devriez faire attention à chaque fois que vous ajoutez une contrainte de clé étrangère est la façon dont vous souhaitez que les mises à jour de la colonne référencée dans une ligne de la table référencée à être traités, et en particulier la façon dont vous voulez les suppressions de lignes dans la table référencée à traiter.

Si une contrainte est créé comme ceci:

alter MyTable
add constraint MyTable_MyColumn_FK FOREIGN KEY ( MyColumn ) 
references MyOtherTable(PKColumn)

.. puis mises à jour ou suppressions dans la table référencée va exploser avec un message d'erreur si il y a une ligne correspondante dans la table de référence.

Cela peut être le comportement que vous voulez, mais dans mon expérience, il est beaucoup plus courant n'est pas.

Si vous au lieu de le créer comme ceci:

alter MyTable
add constraint MyTable_MyColumn_FK FOREIGN KEY ( MyColumn ) 
references MyOtherTable(PKColumn)
on update cascade 
on delete cascade

..puis les mises à jour et des suppressions dans la table parent entraînera des mises à jour et suppressions des lignes correspondantes dans la table de référence.

(Je ne dis pas que la valeur par défaut doit être changé, la valeur par défaut trompe sur le côté de la prudence, qui est la bonne. Je dis juste que c'est quelque chose qu'une personne, qui est la création constaints doit toujours prêter attention à.)

Cela peut être fait, par la manière, lors de la création d'un tableau, comme ceci:

create table ProductCategories (
  Id           int identity primary key,
  ProductId    int references Products(Id)
               on update cascade on delete cascade
  CategoryId   int references Categories(Id) 
               on update cascade on delete cascade
)

14voto

Bijimon Points 123
 create table question_bank
(
    question_id uniqueidentifier primary key,
    question_exam_id uniqueidentifier not null constraint fk_exam_id foreign key references exams(exam_id),
    question_text varchar(1024) not null,
    question_point_value decimal
);
 

- Cela fonctionnera aussi. Peut-être une construction un peu plus intuitive?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X