Добавление связи внешнего ключа между двумя базами данных


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

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

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

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

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

6 53

6 ответов:

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


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

пример:

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

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

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

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

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

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

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

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)

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

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

см. SQL docs @ http://msdn.microsoft.com/en-us/library/aa258254%28v=sql.80%29.aspx В каком состоянии:

триггеры часто используются для реализации бизнес-правила и целостность данных. язык SQL Сервер предоставляет декларативный ссылочная целостность (DRI) до конца инструкции по созданию таблицы (ALTER Таблица и создать таблицу); однако, DRI не предоставляет кросс-базу данных ссылочная целостность. Принуждать ссылочная целостность (правила о отношения между первичным и внешние ключи таблиц), использовать первичные и ограничения внешнего ключа (в Первичный ключ и внешний ключ ключевые слова изменить таблицу и создать таблицу). Если ограничения существуют на триггере таблица, они проверяются после Вместо выполнения триггера и предшествующего после выполнения триггера. Если ограничения нарушаются, вместо этого Триггерных действий откатываются и триггер AFTER не выполняется (обожженный.)

существует также ОК обсуждение на SQLTeam - http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=31135

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