두 데이터베이스 간의 외래 키 관계 추가


90

두 개의 서로 다른 데이터베이스에 두 개의 테이블이 있습니다. table1 (database1에 있음)에는 column1이라는 열이 있으며 기본 키입니다. 이제 table2 (database2)에 column2라는 열이 있으며이를 외래 키로 추가하고 싶습니다.

추가하려고했는데 다음과 같은 오류가 발생했습니다.

메시지 1763, 수준 16, 상태 0, 줄 1
데이터베이스 간 외래 키 참조는 지원되지 않습니다. 외래 키 Database2.table2.

메시지 1750, 수준 16, 상태 0, 줄 1
제약 조건을 만들 수 없습니다. 이전 오류를 참조하십시오.

테이블이 다른 데이터베이스에 있기 때문에 어떻게해야합니까?

답변:


84

트리거를 사용하여 데이터베이스 전체에서 참조 제한 조건을 관리해야합니다.


기본적으로 삽입, 업데이트 트리거를 생성하여 기본 키 테이블에 키가 있는지 확인합니다. 키가 없으면 삽입 또는 업데이트를 되 돌린 다음 예외를 처리하십시오.

예:

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

수정 됨 : 명확히하기 위해. 이것은 참조 무결성을 적용하는 최선의 방법이 아닙니다. 이상적으로는 동일한 db에있는 두 테이블을 모두 원하지만 가능하지 않은 경우입니다. 그렇다면 위의 방법은 잠재적 인 해결 방법입니다.


3
@John Hartsock-위의 예는 적절한 트랜잭션 처리를 추가하지 않고도 쉽게 실패 할 수 있습니다. "if not
exist

16
@John Hartsock-솔루션에 허점이 있습니다. 두 데이터베이스 중 하나가 백업에서 복원되면 당연히 트리거가 실행되지 않습니다. 이것이 고아 행으로 끝날 수있는 방법입니다.
AK

4
@AlexKuznetsov 맞습니다. 내가 설명했듯이 이것은 최선의 접근 방식은 아니지만 잠재적 인 해결 방법입니다.
John Hartsock 2011 년

2
이건 너무 잘못 됐어 ... 난 OP가 그가 이런 걸 요구한다는 사실이 그가 뭔가 잘못하고있을 가능성이 가장 높다는 사실을 깨닫기를 바랍니다 ... 방아쇠에 대해 생각하는 것은 말할 것도 없습니다.
MeTitus

1
@Marco 내가 내 대답에 게시 한대로 "명확하게 설명하겠습니다. 이것은 참조 무결성을 적용하는 최선의 방법이 아닙니다. 이상적으로는 동일한 DB에 두 테이블을 모두 원하지만 가능하지 않은 경우 위의 방법은 잠재적 인 해결 방법입니다. 당신." 나는 이것이 아마도 좋은 생각이 아니라고 설명했다.
John Hartsock 2014 년

48

견고한 무결성이 필요한 경우 하나의 데이터베이스에 두 테이블을 모두 포함하고 FK 제약 조건을 사용하십시오. 상위 테이블이 다른 데이터베이스에있는 경우 다른 사람이 이전 백업에서 해당 상위 데이터베이스를 복원하는 것을 방해하는 것은 없으며 고아가됩니다.

이것이 데이터베이스 간의 FK가 지원되지 않는 이유입니다.


27

내 경험상, 관련된 두 테이블에 대한 기본 정보 소스가 두 개의 별도 데이터베이스에 있어야 할 때이를 처리하는 가장 좋은 방법은 기본 위치에서 보조 위치로 테이블 사본을 동기화하는 것입니다 (T- 적절한 오류 검사가있는 SQL 또는 SSIS-테이블에 외래 키 참조가있는 동안에는 테이블을 자르고 다시 채울 수 없으므로 테이블 업데이트시 고양이를 스키닝하는 몇 가지 방법이 있습니다.

그런 다음 두 번째 위치의 기존 FK 관계를 사실상 읽기 전용 복사 본인 테이블에 추가합니다.

기본 위치에서 트리거 또는 예약 된 작업을 사용하여 복사본을 업데이트 할 수 있습니다.


1
레. "주 위치에서 작업을 트리거하거나 예약하여 복사본을 업데이트 할 수 있습니다.": SQL Server 복제 (구체적으로 구독자의 복사본 (외래 키 제약 조건이 필요한 테이블이있는 복사본) 이후의 트랜잭션 대 병합 유형)를 사용하면 안됩니다. 읽기 전용이어야 함)? 참조 : 링크
Tom

@Tom 예, 복제를 사용하여 원격 데이터베이스에서 업데이트 된 테이블의 복사본을 유지할 수 있습니다.
Cade Roux

20

사용자 정의 함수와 함께 검사 제약 조건을 사용하여 검사를 수행 할 수 있습니다. 방아쇠보다 더 신뢰할 수 있습니다. 외래 키와 동일하게 필요할 때 비활성화하고 다시 활성화 할 수 있으며 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)

1
이것은 허용 된 답변보다 더 나은 솔루션이며 여러 테이블에서 재사용 할 수도 있습니다
Milox

3

짧은 대답은 SQL Server (SQL 2008 기준)가 오류 메시지에 나와있는 것처럼 데이터베이스 간 외래 키를 지원하지 않는다는 것입니다.

선언적 참조 무결성 (FK)을 가질 수는 없지만 트리거를 사용하여 동일한 목표에 도달 할 수 있습니다. 작성하는 로직에 버그가있을 수 있기 때문에 약간 덜 신뢰할 수 있지만 똑같이 얻을 수 있습니다.

http://msdn.microsoft.com/en-us/library/aa258254%28v=sql.80%29.aspx 에서 SQL 문서를 참조하십시오 .

트리거는 종종 비즈니스 규칙 및 데이터 무결성을 적용하는 데 사용됩니다. SQL Server는 테이블 생성 문 (ALTER TABLE 및 CREATE TABLE)을 통해 선언적 참조 무결성 (DRI)을 제공합니다. 그러나 DRI는 데이터베이스 간 참조 무결성을 제공하지 않습니다. 참조 무결성 (테이블의 기본 키와 외래 키 간의 관계에 대한 규칙)을 적용하려면 기본 및 외래 키 제약 조건 (ALTER TABLE 및 CREATE TABLE의 PRIMARY KEY 및 FOREIGN KEY 키워드)을 사용합니다. 트리거 테이블에 제약 조건이있는 경우 INSTEAD OF 트리거 실행 후 및 AFTER 트리거 실행 전에 확인됩니다. 제약 조건을 위반하면 INSTEAD OF 트리거 동작이 롤백되고 AFTER 트리거가 실행 (실행)되지 않습니다.

SQLTeam- http ://www.sqlteam.com/forums/topic.asp?TOPIC_ID=31135에서도 OK 토론이 있습니다 .


0

오류 메시지에서 알 수 있듯이 SQL Server에서는 지원되지 않습니다. 굴절 무결성을 보장하는 유일한 방법은 트리거를 사용하는 것입니다.


1
당신은 예를 들어 나를 설명 할 수
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.