괴롭힘.
누군가가 여기에 도착하면 고유하지 않은 키가 포함 된 테이블의 열에 외래 키가 필요하다고 가정합니다.
문제는 해당 문제가있는 경우 데이터베이스 스키마가 비정규 화 된 것입니다.
예를 들어 room-uid 기본 키, DateFrom 및 DateTo 필드 및 다른 uid (여기서 동일한 룸을 추적하기위한 RM_ApertureID) 및 RM_Status와 같은 소프트 삭제 필드를 사용하여 테이블에 룸을 유지하고 있습니다. 여기서 99는 '삭제됨'을 의미하고 <> 99는 '활성'을 의미합니다.
따라서 첫 번째 방을 만들 때 RM_UID와 동일한 값으로 RM_UID 및 RM_ApertureID를 삽입합니다. 그런 다음 회의실을 날짜로 종료하고 새 날짜 범위로 다시 설정하면 RM_UID는 newid ()이며 이전 항목의 RM_ApertureID는 새로운 RM_ApertureID가됩니다.
따라서이 경우 RM_ApertureID는 고유하지 않은 필드이므로 다른 테이블에서 외래 키를 설정할 수 없습니다.
그리고 외래 키를 고유하지 않은 열 / 인덱스로 설정하는 방법은 없습니다 (예 : T_ZO_REM_AP_Raum_Reinigung (WHERE RM_UID는 실제로 RM_ApertureID)).
그러나 유효하지 않은 값을 방지하려면 외래 키를 설정해야합니다. 그렇지 않으면 데이터 가비지가 나중에보다 빨리 발생합니다.
이제이 경우 (전체 응용 프로그램을 다시 작성하지 않는 것) 할 수있는 것은 키의 존재를 확인하는 스칼라 함수와 함께 CHECK 제약 조건을 삽입하는 것입니다.
IF EXISTS (SELECT * FROM sys.check_constraints WHERE object_id = OBJECT_ID(N'[dbo].[Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_ZO_REM_AP_Raum_Reinigung]'))
ALTER TABLE dbo.T_ZO_REM_AP_Raum_Reinigung DROP CONSTRAINT [Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[fu_Constaint_ValidRmApertureId]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[fu_Constaint_ValidRmApertureId]
GO
CREATE FUNCTION [dbo].[fu_Constaint_ValidRmApertureId](
@in_RM_ApertureID uniqueidentifier
,@in_DatumVon AS datetime
,@in_DatumBis AS datetime
,@in_Status AS integer
)
RETURNS bit
AS
BEGIN
DECLARE @bNoCheckForThisCustomer AS bit
DECLARE @bIsInvalidValue AS bit
SET @bNoCheckForThisCustomer = 'false'
SET @bIsInvalidValue = 'false'
IF @in_Status = 99
RETURN 'false'
IF @in_DatumVon > @in_DatumBis
BEGIN
RETURN 'true'
END
IF @bNoCheckForThisCustomer = 'true'
RETURN @bIsInvalidValue
IF NOT EXISTS
(
SELECT
T_Raum.RM_UID
,T_Raum.RM_Status
,T_Raum.RM_DatumVon
,T_Raum.RM_DatumBis
,T_Raum.RM_ApertureID
FROM T_Raum
WHERE (1=1)
AND T_Raum.RM_ApertureID = @in_RM_ApertureID
AND @in_DatumVon >= T_Raum.RM_DatumVon
AND @in_DatumBis <= T_Raum.RM_DatumBis
AND T_Raum.RM_Status <> 99
)
SET @bIsInvalidValue = 'true' -- IF !
RETURN @bIsInvalidValue
END
GO
IF EXISTS (SELECT * FROM sys.check_constraints WHERE object_id = OBJECT_ID(N'[dbo].[Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_ZO_REM_AP_Raum_Reinigung]'))
ALTER TABLE dbo.T_ZO_REM_AP_Raum_Reinigung DROP CONSTRAINT [Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung]
GO
-- ALTER TABLE dbo.T_AP_Kontakte WITH CHECK ADD CONSTRAINT [Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung]
ALTER TABLE dbo.T_ZO_REM_AP_Raum_Reinigung WITH NOCHECK ADD CONSTRAINT [Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung]
CHECK
(
NOT
(
dbo.fu_Constaint_ValidRmApertureId(ZO_RMREM_RM_UID, ZO_RMREM_GueltigVon, ZO_RMREM_GueltigBis, ZO_RMREM_Status) = 1
)
)
GO
IF EXISTS (SELECT * FROM sys.check_constraints WHERE object_id = OBJECT_ID(N'[dbo].[Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung]') AND parent_object_id = OBJECT_ID(N'[dbo].[T_ZO_REM_AP_Raum_Reinigung]'))
ALTER TABLE dbo.T_ZO_REM_AP_Raum_Reinigung CHECK CONSTRAINT [Check_RM_ApertureIDisValid_T_ZO_REM_AP_Raum_Reinigung]
GO
table1.ID않습니까?