简体   繁体   English

SQL:外键引用复合主键

[英]SQL: Foreign key references a composite primary key

I'm new to SQL and there are a lot of things going on that I still don't seem to quite understand. 我是SQL的新手,有很多事情发生,我似乎还不太明白。 I have the following table 我有下表

CREATE TABLE Person 
(
    First_Name varchar(20) NOT NULL,
    Name varchar(20) NOT NULL,
    Address varchar(50) NOT NULL,

    PRIMARY KEY (First_Name, Name, Address)
);

I know want to create another table that has the primary key from the table Person as foreign key and also as primary key: 我知道要创建另一个表,该表具有表Person作为外键的主键以及主键:

CREATE TABLE Purchase 
(
    No_Installments int,
    Rate int,
    Person varchar(50) NOT NULL PRIMARY KEY,

    CONSTRAINT PFK 
        FOREIGN KEY (Person) REFERENCES Person (First_Name, Name, Address)
);

For some reason this doesn't work and I get an error every time. 出于某种原因,这不起作用,每次都会出错。 I've already looked up the other threads here on stackoverflow, but they don't really seem to help me. 我已经在stackoverflow上查找了其他线程,但它们似乎并没有真正帮助我。 What am I doing wrong? 我究竟做错了什么?

If you have a compound PK made up from three columns, then any child table that wants to establish a foreign key relationship must ALSO have all those 3 columns and use all 3 columns to establish the FK relationship. 如果您有一个由三列组成的复合PK ,那么任何想要建立外键关系的子表都必须包含所有这三列并使用所有3列来建立FK关系。

FK-PK relationship is an all or nothing proposal - you cannot reference only parts of a primary key - either you reference all columns - or you don't reference. FK-PK关系是一个全有或全无的提议 - 您不能仅引用主键的部分 - 您可以引用所有列 - 或者您不引用。

CREATE TABLE Purchase 
(
    No_Installments int,
    Rate int,

    Person varchar(50) NOT NULL PRIMARY KEY,

    First_Name varchar(20) NOT NULL,
    Name varchar(20) NOT NULL,
    Address varchar(50) NOT NULL,

    CONSTRAINT PFK 
        FOREIGN KEY (First_Name, Name, Address) 
        REFERENCES Person (First_Name, Name, Address)
);

Have an integer primary key, using identity , auto_increment , serial or whatever for your database: 拥有一个整数主键,使用identityauto_incrementserial或其他适用于您的数据库:

CREATE TABLE Person (
    PersonId int identity PRIMARY KEY
    First_Name varchar(20) NOT NULL,
    Name varchar(20) NOT NULL,
    Address varchar(50) NOT NULL,
    CONSTRAINT unq_person_3 UNIQUE (First_Name, Name, Address)
);

Then use the identity column for the reference: 然后使用标识列作为参考:

CREATE TABLE Purchase (
    PurchaseId int identity PRIMARY KEY,
    No_Installments int,
    Rate int,
    PersonId int,
    CONSTRAINT PFK 
        FOREIGN KEY (PersonId) REFERENCES Person (PersonId)
);

Notes: 笔记:

  • You really don't want to have to deal with a composite primary key. 您真的不想处理复合主键。 Have you thought about what the joins will look like? 你有没有想过连接会是什么样的?
  • You don't want a primary key where the values are subject to change. 您不希望主键可以更改值。 What happens when someone changes his/her name? 当有人改变他/她的名字会发生什么? When someone moves? 当有人移动?
  • Person should not be the primary key in Purchases . Person不应该是Purchases的主要关键。 Are you only allowing someone to make one purchase? 你只允许某人购买吗?
  • As noted initially, how you generate such a column varies by database; 如前所述,生成此类列的方式因数据库而异; identity happens to be the way that SQL Server does this. identity恰好是SQL Server执行此操作的方式。

You probably want to assign a unique ID to each person, not relying on their name to be unique or for an address to be required. 您可能希望为每个人分配一个唯一的ID,而不是依赖于他们的名称是唯一的,或者是否需要一个地址。 That ID will be your Primary key and foreign key. 该ID将是您的主键和外键。 Your purchase table should also have its own id for its primary key -- otherwise because primary keys must be unique, each person can only have one purchase. 您的购买表也应该有自己的主键ID - 否则因为主键必须是唯一的,每个人只能购买一次。

CREATE TABLE Person (
   id serial NOT NULL,
   First_Name varchar(20) NOT NULL,
   Name varchar(20) NOT NULL,
   Address varchar(50) NOT NULL,
   PRIMARY KEY (id));

CREATE TABLE Purchase (
   id serial NOT NULL,
   No_Installments int,
   Rate int,
   Person int NOT NULL,
   FOREIGN KEY (Person) REFERENCES Person (id), 
   PRIMARY KEY (id));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM