Necromance.
Tôi giả sử khi ai đó hạ cánh ở đây, anh ta cần một khóa ngoại để cột trong một bảng có chứa các khóa không duy nhất.
Vấn đề là, nếu bạn gặp vấn đề đó, lược đồ cơ sở dữ liệu bị không chuẩn hóa.
Ví dụ, bạn đang giữ các phòng trong một bảng, với khóa chính là phòng, một trường DateFrom và DateTo, và một uid khác, ở đây là RM_ApertureID để theo dõi cùng một phòng và một trường xóa mềm, như RM_Status, trong đó 99 có nghĩa là 'đã xóa' và <> 99 có nghĩa là 'hoạt động'.
Vì vậy, khi bạn tạo phòng đầu tiên, bạn chèn RM_UID và RM_ApertureID có cùng giá trị với RM_UID. Sau đó, khi bạn chấm dứt phòng đến một ngày và thiết lập lại nó với một phạm vi ngày mới, RM_UID là newid () và RM_ApertureID từ mục trước đó trở thành RM_ApertureID mới.
Vì vậy, nếu đó là trường hợp, RM_ApertureID là một trường không phải là duy nhất và vì vậy bạn không thể đặt khóa ngoại trong một bảng khác.
Và không có cách nào để đặt khóa ngoại thành một cột / chỉ mục không duy nhất, ví dụ như trong T_ZO_REM_AP_Raum_Reinigung (WHERE RM_UID thực sự là RM_ApertureID).
Nhưng để cấm các giá trị không hợp lệ, bạn cần đặt khóa ngoại, nếu không, rác dữ liệu là kết quả sớm hơn là sau này ...
Bây giờ, những gì bạn có thể làm trong trường hợp này (viết tắt toàn bộ ứng dụng) là chèn một ràng buộc CHECK, với hàm vô hướng kiểm tra sự hiện diện của khóa:
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
?