Добавить отношение внешнего ключа между двумя базами данных - PullRequest
65 голосов
/ 15 декабря 2010

У меня есть две таблицы в двух разных базах данных.В таблице 1 (в базе данных 1) есть столбец с именем column1, и это первичный ключ.Теперь в таблице 2 (в базе данных 2) есть столбец с именем column2, и я хочу добавить его как внешний ключ.

Я попытался добавить его, и он выдал следующую ошибку:

Сообщение 1763, Уровень 16, Состояние 0, Строка 1
Ссылки внешнего ключа между базами данных не поддерживаются.Внешний ключ Database2.table2.

Сообщение 1750, уровень 16, состояние 0, строка 1
Не удалось создать ограничение.См. Предыдущие ошибки.

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

Ответы [ 6 ]

65 голосов
/ 15 декабря 2010

Вам потребуется управлять ссылочным ограничением в базах данных с помощью триггера.


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

Пример:

Create Trigger dbo.MyTableTrigger ON dbo.MyTable, After Insert, Update
As
Begin

   If NOT Exists(select PK from OtherDB.dbo.TableName where PK in (Select FK from inserted) BEGIN
      -- Handle the Referential Error Here
   END

END

Отредактировано: Просто чтобы уточнить. Это не лучший подход к обеспечению ссылочной целостности. В идеале вы хотели бы, чтобы обе таблицы были в одном и том же БД, но если это невозможно. Тогда вышесказанное - это потенциальный обходной путь для вас.

37 голосов
/ 15 декабря 2010

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

Именно поэтому FK между базами данных не поддерживается.

23 голосов
/ 15 декабря 2010

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

Затем добавьте традиционное отношение FK во втором расположении к таблице, которая фактически является копией только для чтения.

Вы можете использовать триггер или запланированное задание в основном расположении для обновления копии.

16 голосов
/ 12 ноября 2015

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

CREATE FUNCTION dbo.fn_db2_schema2_tb_A
(@column1 INT) 
RETURNS BIT
AS
BEGIN
    DECLARE @exists bit = 0
    IF EXISTS (
      SELECT TOP 1 1 FROM DB2.SCHEMA2.tb_A 
      WHERE COLUMN_KEY_1 =  @COLUMN1
    ) BEGIN 
         SET @exists = 1 
      END;
      RETURN @exists
END
GO

ALTER TABLE db1.schema1.tb_S
  ADD CONSTRAINT CHK_S_key_col1_in_db2_schema2_tb_A
    CHECK(dbo.fn_db2_schema2_tb_A(key_col1) = 1)
3 голосов
/ 15 декабря 2010

Краткий ответ: SQL Server (начиная с SQL 2008) не поддерживает внешние ключи базы данных - как говорится в сообщении об ошибке.

Хотя вы не можете иметь декларативную ссылочную целостность (FK), вы можете достичь той же цели с помощью триггеров. Это немного менее надежно, потому что в логике, которую вы пишете, могут быть ошибки, но она точно так же поможет вам.

См. Документы SQL @ http://msdn.microsoft.com/en-us/library/aa258254%28v=sql.80%29.aspx Какое состояние:

Триггеры часто используются для обеспечения соблюдения бизнес-правила и целостность данных. SQL Сервер предоставляет декларативный ссылочная целостность (DRI) через операторы создания таблицы (ALTER СТОЛ и СОЗДАТЬ СТОЛ); однако DRI не предоставляет кросс-базы данных ссылочная целостность. Укреплять ссылочная целостность (правила о отношения между первичной и внешние ключи таблиц), используйте первичные и ограничения внешнего ключа ( ПЕРВИЧНЫЙ КЛЮЧ И КЛЮЧЕВОЙ КЛЮЧ ALTER TABLE и CREATE TABLE). Если существуют ограничения на триггер таблицы, они проверяются после ВМЕСТО выполнения триггера и до ПОСЛЕ выполнения триггера. Если ограничения нарушены, ВМЕСТО Триггерные действия откатываются и триггер AFTER не выполняется (Уволен). * * 1 010

В SQLTeam также обсуждается вопрос "ОК" - http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=31135

0 голосов
/ 15 декабря 2010

Как говорится в сообщении об ошибке, это не поддерживается на сервере SQL. Единственный способ обеспечить ссылочную целостность - это работать с триггерами.

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