Внешний ключ, используемый в составном первичном ключе

Спасибо за чтение.

можно ли использовать составной внешний ключ в качестве части составного первичного ключа таблицы?

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

            CREATE TABLE DB.dbo.Partners
            (
                CONSTRAINT pk_Partners_Id
                PRIMARY KEY (Name, City, State, Country, PostalCode),

                Name                VARCHAR(100)
                                    NOT NULL,

                Address1            VARCHAR(100),

                Address2            VARCHAR(100),

                Address3            VARCHAR(100),

                City                VARCHAR(150)
                                    NOT NULL,

                State               CHAR(2)
                                    NOT NULL,

                Country             CHAR(2)
                                    NOT NULL,

                PostalCode          VARCHAR(16)
                                    NOT NULL,

                Phone               VARCHAR(20),

                Fax                 VARCHAR(20),

                Email               VARCHAR(256)
            )

... и затем во второй таблице я хотел бы сослаться на внешний ключ во втором первичном ключе таблицы:

            CREATE TABLE DB.dbo.PartnerContacts
            (
                CONSTRAINT pk_PartnerContacts_Id
                PRIMARY KEY (fk_PartnerContacts_PartnerId, FirstName, LastName, PhoneNumber, Email),

                CONSTRAINT fk_PartnerContacts_PartnerId
                FOREIGN KEY REFERENCES Partners(Name, City, State, Country, PostalCode),

                FirstName           VARCHAR(75)
                                    NOT NULL,

                MiddleName          VARCHAR(75),

                LastName            VARCHAR(75)
                                    NOT NULL,

                PhoneNumber         VARCHAR(20)
                                    NOT NULL,

                MobileNumber        VARCHAR(20),

                FaxNumber           VARCHAR(20),

                Email               VARCHAR(256)
                                    NOT NULL,

                MailTo              VARCHAR(100),

                Address1            VARCHAR(100),

                Address2            VARCHAR(100),

                Address3            VARCHAR(100),

                City                VARCHAR(150),

                State               CHAR(2),

                Country             CHAR(2),

                PostalCode          VARCHAR(16)
            )

есть ли способ, которым я могу это сделать? Да, может быть проще просто использовать столбцы идентификаторов в этих таблицах, но если я могу определить фактические отношения без личности я хотел бы сделать это.

EDIT:

Я хотел предоставить окончательный, рабочий SQL. Спасибо всем, кто ответил!

            CREATE TABLE DB.dbo.Partners
            (
                CONSTRAINT pk_Partners_Id
                PRIMARY KEY (Name, City, State, Country, PostalCode),

                Id                  INT
                                    NOT NULL
                                    UNIQUE
                                    IDENTITY(1, 1),

                Name                VARCHAR(100)
                                    NOT NULL,

                Address1            VARCHAR(100),

                Address2            VARCHAR(100),

                Address3            VARCHAR(100),

                City                VARCHAR(150)
                                    NOT NULL,

                State               CHAR(2)
                                    NOT NULL,

                Country             CHAR(2)
                                    NOT NULL,

                PostalCode          VARCHAR(16)
                                    NOT NULL,

                Phone               VARCHAR(20),

                Fax                 VARCHAR(20),

                Email               VARCHAR(256)
            )

            CREATE TABLE DB.dbo.PartnerContacts
            (
                CONSTRAINT pk_PartnerContacts_Id
                PRIMARY KEY
                (PartnerId, FirstName, LastName, PhoneNumber, Email),

                PartnerId           INT
                                    NOT NULL
                                    CONSTRAINT fk_PartnerContacts_PartnerId
                                    FOREIGN KEY REFERENCES Partners(Id),

                FirstName           VARCHAR(75)
                                    NOT NULL,

                MiddleName          VARCHAR(75),

                LastName            VARCHAR(75)
                                    NOT NULL,

                PhoneNumber         VARCHAR(20)
                                    NOT NULL,

                MobileNumber        VARCHAR(20),

                FaxNumber           VARCHAR(20),

                Email               VARCHAR(256)
                                    NOT NULL,

                MailTo              VARCHAR(100),

                Address1            VARCHAR(100),

                Address2            VARCHAR(100),

                Address3            VARCHAR(100),

                City                VARCHAR(150),

                State               CHAR(2),

                Country             CHAR(2),

                PostalCode          VARCHAR(16)
            )

спасибо :)

3 ответов


вы, вероятно, нужно указать столбцы, которые должны совпадать.

CONSTRAINT fk_PartnerContacts_PartnerId
FOREIGN KEY         (columns that correspond to referenced columns) 
 REFERENCES Partners (Name, City, State, Country, PostalCode),

поэтому вам нужно указать пять имен столбцов, значения которых должны соответствовать значениям {Name, City, State, Country, PostalCode} в таблице "Partners". я почти уверен, что вы не можете сделать это с вашей нынешней структурой. Вы не сможете сопоставить "имя". Я думаю, вы ищете что-то в этом роде.

CREATE TABLE DB.dbo.PartnerContacts (
-- Start with columns that identify "Partner".
    partner_name VARCHAR(100) NOT NULL,
    partner_city VARCHAR(150) NOT NULL,
    partner_state CHAR(2) NOT NULL,
    partner_country CHAR(2) NOT NULL,
    partner_postcode VARCHAR(16) NOT NULL,
    CONSTRAINT fk_PartnerContacts_PartnerId
        FOREIGN KEY (partner_name, partner_city, partner_state, partner_country, partner_postcode) 
        REFERENCES Partners (Name, City, State, Country, PostalCode),
    FirstName    VARCHAR(75) NOT NULL,
    MiddleName   VARCHAR(75),
    LastName     VARCHAR(75) NOT NULL,
    PhoneNumber  VARCHAR(20) NOT NULL,
    MobileNumber VARCHAR(20),
    FaxNumber    VARCHAR(20),
    Email        VARCHAR(256) NOT NULL,
    MailTo       VARCHAR(100),
    Address1     VARCHAR(100),
    Address2     VARCHAR(100),
    Address3     VARCHAR(100),
    City         VARCHAR(150),
    State        CHAR(2),
    Country      CHAR(2),
    PostalCode   VARCHAR(16),
    CONSTRAINT pk_PartnerContacts_Id
    PRIMARY KEY (partner_name, partner_city, partner_state, partner_country, partner_postcode, 
                 FirstName, LastName, PhoneNumber, Email)
);

Да, это возможно и обычно считается лучшей практикой проектирования БД, но практически столбец ID просто легче иметь дело. Подумайте о таблицах join, их первичный ключ представляет собой смесь двух внешних ключей. Нет никакой разницы в использовании нескольких внешних ключей как части составного первичного ключа.


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

давайте немного упростим вариант использования для приведенного ниже примера.

скажем, у нас есть таблица test1, имеющая составной первичный ключ (A, B)

Теперь мы можем иметь таблицу, скажем test2, имеющую первичный ключ (P, Q, R), где в (P,Q) ссылок test2 (A, B) test1.

я запустил следующий скрипт в базе данных MySql и она работает просто отлично.

CREATE TABLE `test1` (
`A` INT NOT NULL,
`B` VARCHAR(2) NOT NULL,
`C` DATETIME NULL,
`D` VARCHAR(45) NULL,
PRIMARY KEY (`A`, `B`));


CREATE TABLE `test2` (
`P` INT NOT NULL,
`Q` VARCHAR(2) NOT NULL,
`R` INT NOT NULL,
`S` DATETIME NULL,
`T` VARCHAR(8) NULL,
PRIMARY KEY (`P`, `Q`, `R`),
INDEX `PQ_idx` (`P`,`Q` ASC),
CONSTRAINT `PQ`
  FOREIGN KEY (`P`, `Q`)
  REFERENCES `test1` (`A`,`B`)
  ON DELETE CASCADE
  ON UPDATE CASCADE);

в вышеупомянутом случае база данных ожидает, что комбинация (A, B) будет уникальной, и она является первичным ключом в таблице test1.


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

CREATE TABLE `test2` (
`P` INT NOT NULL,
`Q` VARCHAR(2) NULL,
`R` DATETIME NULL,
`S` VARCHAR(8) NULL,
`T` VARCHAR(45) NULL,
  INDEX `P_idx` (`P` ASC),
  INDEX `Q_idx` (`Q` ASC),
  CONSTRAINT `P`
    FOREIGN KEY (`P`)
    REFERENCES `test1` (`A`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `Q`
    FOREIGN KEY (`Q`)
    REFERENCES `test1` (`B`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);

в вышеупомянутой базе данных case ожидается, что столбец A будет уникально индивидуально и то же самое следует для столбца B. не имеет значения,является ли комбинация (A, B) уникальной.