确保外键的外键与基本外键匹配
Ensure foreign key of a foreign key matches a base foreign key
基本上假设我有一个 "Business" 拥有它所服务的邮政编码。我们还假设我有另一个设置费用的关系 table。
CREATE TABLE [dbo].[BusinessPostalCodes]
(
[BusinessPostalCodeId] INT IDENTITY (1, 1) NOT NULL,
[BusinessId] INT NOT NULL,
[PostalCode] VARCHAR (10) NOT NULL
)
CREATE TABLE [dbo].[BusinessPostalCodeFees]
(
[BusinessId] INT NOT NULL,
[BusinessProfileFeeTypeId] INT NOT NULL,
[BusinessPostalCodeId] INT NOT NULL,
[Fee] SMALLMONEY NULL
)
我想知道是否可以在 BusinessPostalCodeFees
上设置外键(或其他东西)以确保 BusinessPostalCodes
的相关 BusinessId
与 BusinessId
共 BusinessPostalCodeFees
。
我知道我可以完全删除 BusinessId
,但我更愿意保留此专栏并有办法保证它们相同。有什么我可以做的吗?
这听起来像是(如果我错了请纠正我)您正在尝试确保 BusinessPostalCodeFees 的 BusinessId 和 BusinessPostalCodeId 列中的任何条目与 BusinessPostalCodes table 中的条目相匹配。如果是这样,那么可以 definitely have a foreign key that references a compound primary key.
但是,如果您需要保留 BusinessId,我建议您对 table 进行规范化,比您做的更进一步。您最终将按原样获得重复数据。
附带说明一下,我建议您不要使用 SQL 中的货币数据类型:See here.
最后,Jeffrey 的解决方案并不完全适合我的具体情况。关系中的两列都必须是唯一的(如复合键)。结果这里的答案(对我来说)是 Checked Constraint.
创建一个您希望约束通过或失败的函数:
CREATE FUNCTION [dbo].[MatchingBusinessIdPostalCodeAndProfileFeeType]
(
@BusinessId int,
@BusinessPostalCodeId int,
@BusinessProfileFeeTypeId int
)
RETURNS BIT
AS
BEGIN
-- This works because BusinessPostalCodeId is a unique Id.
-- If businessId doesn't match, its filtered out.
DECLARE @pcCount AS INT
SET @pcCount = (SELECT COUNT(*)
FROM BusinessPostalCodes
WHERE BusinessPostalCodeId = @BusinessPostalCodeId AND
BusinessId = @BusinessId)
-- This works because BusinessProfileFeeTypeId is a unique Id.
-- If businessId doesn't match, its filtered out.
DECLARE @ftCount AS INT
SET @ftCount = (SELECT COUNT(*)
FROM BusinessProfileFeeTypes
WHERE BusinessProfileFeeTypeId = @BusinessProfileFeeTypeId AND
BusinessId = @BusinessId)
-- Both should have only one record
BEGIN IF (@pcCount = 1 AND @ftCount = 1)
RETURN 1
END
RETURN 0
END
然后将其添加到您的 table:
CONSTRAINT [CK_BusinessPostalCodeFees_MatchingBusinessIdPostalCodeAndProfileFeeType]
CHECK (dbo.MatchingBusinessIdPostalCodeAndProfileFeeType(
BusinessId,
BusinessPostalCodeId,
BusinessProfileFeeTypeId) = 1)
基本上假设我有一个 "Business" 拥有它所服务的邮政编码。我们还假设我有另一个设置费用的关系 table。
CREATE TABLE [dbo].[BusinessPostalCodes]
(
[BusinessPostalCodeId] INT IDENTITY (1, 1) NOT NULL,
[BusinessId] INT NOT NULL,
[PostalCode] VARCHAR (10) NOT NULL
)
CREATE TABLE [dbo].[BusinessPostalCodeFees]
(
[BusinessId] INT NOT NULL,
[BusinessProfileFeeTypeId] INT NOT NULL,
[BusinessPostalCodeId] INT NOT NULL,
[Fee] SMALLMONEY NULL
)
我想知道是否可以在 BusinessPostalCodeFees
上设置外键(或其他东西)以确保 BusinessPostalCodes
的相关 BusinessId
与 BusinessId
共 BusinessPostalCodeFees
。
我知道我可以完全删除 BusinessId
,但我更愿意保留此专栏并有办法保证它们相同。有什么我可以做的吗?
这听起来像是(如果我错了请纠正我)您正在尝试确保 BusinessPostalCodeFees 的 BusinessId 和 BusinessPostalCodeId 列中的任何条目与 BusinessPostalCodes table 中的条目相匹配。如果是这样,那么可以 definitely have a foreign key that references a compound primary key.
但是,如果您需要保留 BusinessId,我建议您对 table 进行规范化,比您做的更进一步。您最终将按原样获得重复数据。
附带说明一下,我建议您不要使用 SQL 中的货币数据类型:See here.
最后,Jeffrey 的解决方案并不完全适合我的具体情况。关系中的两列都必须是唯一的(如复合键)。结果这里的答案(对我来说)是 Checked Constraint.
创建一个您希望约束通过或失败的函数:
CREATE FUNCTION [dbo].[MatchingBusinessIdPostalCodeAndProfileFeeType]
(
@BusinessId int,
@BusinessPostalCodeId int,
@BusinessProfileFeeTypeId int
)
RETURNS BIT
AS
BEGIN
-- This works because BusinessPostalCodeId is a unique Id.
-- If businessId doesn't match, its filtered out.
DECLARE @pcCount AS INT
SET @pcCount = (SELECT COUNT(*)
FROM BusinessPostalCodes
WHERE BusinessPostalCodeId = @BusinessPostalCodeId AND
BusinessId = @BusinessId)
-- This works because BusinessProfileFeeTypeId is a unique Id.
-- If businessId doesn't match, its filtered out.
DECLARE @ftCount AS INT
SET @ftCount = (SELECT COUNT(*)
FROM BusinessProfileFeeTypes
WHERE BusinessProfileFeeTypeId = @BusinessProfileFeeTypeId AND
BusinessId = @BusinessId)
-- Both should have only one record
BEGIN IF (@pcCount = 1 AND @ftCount = 1)
RETURN 1
END
RETURN 0
END
然后将其添加到您的 table:
CONSTRAINT [CK_BusinessPostalCodeFees_MatchingBusinessIdPostalCodeAndProfileFeeType]
CHECK (dbo.MatchingBusinessIdPostalCodeAndProfileFeeType(
BusinessId,
BusinessPostalCodeId,
BusinessProfileFeeTypeId) = 1)