Подтвердить что ты не робот

Создание составного внешнего ключа в SQL Server 2008

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

Первичная таблица

PK - Key1 - varchar(20)
PK - Key2 - date

Вторичная таблица

PK - AutoID
FK - Key1 - varchar(20)
FK - Key2 - date

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

Столбцы первичной таблицы не соответствуют первичному ключу или уникальному ограничение.

Во вторичной таблице может быть много записей с теми же Key1 и Key2, чтобы мы сделали первичный ключ автоматически созданным номером.

Любые мысли о том, как я могу настроить отношение внешних ключей между этими двумя таблицами?

4b9b3361

Ответ 1

Некоторые из них сфокусированы, некоторые из них являются контекстом для других, у которых есть какие-то проблемы вроде этого (например, кто-то действительно ищет сначала?)

Первое, что нужно проверить при возникновении проблемы с созданием ключа, - убедиться, что вы не соответствовали типам данных в двух таблицах. Если у вас есть bigint в одном и int в другом, он будет дуть. Это верно для всех ключей, но с большей вероятностью возникает, если вы используете несколько полей. Простая математика показывает причину, по которой шанс увеличивается.

Следующий вопрос - данные. Если вы не можете создать ключ из-за данных, вам нужно выяснить, что существует в дочерней таблице, которая не существует в родительской таблице. LEFT JOIN таблицы (вторичные на второй/левой стороне соединения) и включать только строки, где первичная таблица равна нулю. Вам придется либо создать эти записи в родительской таблице, либо избавиться от них.

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

Что лучше? Новый первичный ключ или работа с составным ключом? Это действительно зависит от характера данных, но я больше люблю использовать производный ключ над естественным ключом или сложным ключом. Но есть моменты, когда работа, необходимая для получения одного ключа с производным полем, - это большая работа.

Ответ 2

Внешний ключ ДОЛЖЕН обращаться к столбцам, которые составляют уникальный индекс (PK или UK) с одинаковым количеством столбцов, их типами и порядком. Например:.

CREATE TABLE PrimaryTable (
  Key1 varchar(20),
  Key2 date)
GO

ALTER TABLE PrimaryTable ADD CONSTRAINT PK
  PRIMARY KEY (Key1, Key2)
GO

CREATE TABLE SecondaryTable (
  AutoID int IDENTITY,
  Key1 varchar(20),
  Key2 date)
GO

ALTER TABLE SecondaryTable ADD CONSTRAINT FK
  FOREIGN KEY (Key1, Key2) REFERENCES PrimaryTable (Key1, Key2)
GO

Ответ 3

Это будет работать:

CREATE TABLE PTable (
     Key1 varchar(20) not null,
     Key2 date not null,
     constraint PK_PTable PRIMARY KEY (Key1,Key2)
)

CREATE TABLE STable (
     AutoID int IDENTITY(1,1) not null primary key,
     Key1 varchar(20) not null,
     Key2 date not null,
     constraint FK_STable_PTable FOREIGN KEY (Key1,Key2) references PTable (Key1,Key2)
)

Что вам нужно сделать, так это получить Management Studio до script ваших таблиц и сравнить их с приведенными выше.

Ответ 4

Здесь есть хорошие ответы, но я хотел бы сделать это еще дальше - ради потомства.

Внешний ключ должен ссылаться на столбец Primary key (уникальный, кластерный индекс) или столбец Unique с ограничениями в другой таблице. В принципе, необходимым компонентом является ограничение Unique. Я бы добавил, что у вас могут быть столбцы с нулевым значением в вашем внешнем ключе, НО, если вы разрешаете nulls в "составном" ключе, SQL пропускает проверку данных в отношении внешнего ключа. Это важный момент, который следует помнить, поскольку основная причина, по которой большинство из нас использует внешние ключи, - обеспечить целостность данных в наших базах данных.

В заключительном примечании я хотел бы явно объявить все мои ключевые имена. Почему, спросите вы? Если вам нужно использовать "полнотекстовое индексирование" в будущем для улучшения возможностей поиска, это не означает, что вы ссылаетесь на все "автогенерируемые" имена ключей. Это не может быть большой проблемой для небольших проектов, для которых не требуется преобразование данных или запланированные полнотекстовые обновления индексов, но если вы создаете сценарий этой функции, вы можете сделать вашу работу более сложной (например, нужно искать фактическое имя вашего основного Ключевое имя по умолчанию: pk_someTable_1248594832828495904).

Вот что я сделал бы в написании SQL, чтобы избежать любых будущих ошибок:

  • Не разрешайте NULL на составные внешние ключи, если это возможно.
  • Явные имена явно используют согласованное соглашение об именах (например, PK_Schema/56_TalbeName_Col1_Col2). Это не только дает вам стандартное имя для ключа, но вы можете легко увидеть из индекса, на какие столбцы ссылаются и в каком порядке.

Код:

CREATE TABLE MySchema.PrimaryTable ( 
  Key1 varchar(20) NOT NULL, 
  Key2 date NOT NULL,
  CONSTRAINT PK_MySchema_PrimaryTable_Key1_Key2 PRIMARY KEY (Key1, Key2)
)
GO 

CREATE TABLE MySchema.SecondaryTable ( 
  AutoID int IDENTITY, 
  Key1 varchar(20) NOT NULL, 
  Key2 date NOT NULL,
  CONSTRAINT FK_MySchema_SecondaryTable_Key1_Key2
     FOREIGN KEY (Key1, Key2) REFERENCES PrimaryTable (Key1, Key2)
)
GO 

OptillectTeam в основном мертв своим ответом. Я просто хотел прояснить несколько важных вещей, о которых раньше не упоминалось. В представлении MSDN есть хорошая ссылка, обсуждающая это и многое другое по внешним ключам: Ограничение внешнего ключа.

Ответ 5

ДЛЯ ДОБАВЛЕНИЯ УНИКАЛЬНОГО ИСПОЛЬЗОВАНИЯ НИЖЕ ЗАПРОСА

   ALTER TABLE [TableName] ADD UNIQUE ([Column1], [Column2]);