确保外键的外键与基本外键匹配

时间:2016-10-03 19:54:18

标签: sql-server tsql foreign-key-relationship

基本上我们说我有一个" Business"拥有它服务的邮政编码。我们还假设我有另一个设置费用的关系表。

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上设置外键(或其他内容),以确保BusinessId的{​​{1}}与BusinessPostalCodes相同BusinessId的{​​{1}}。

我意识到我可以完全删除BusinessPostalCodeFees,但我更愿意保留这个专栏并保证它们是相同的。我有什么可以做的吗?

2 个答案:

答案 0 :(得分:1)

听起来(如果我错了,请纠正我)您正在尝试确保BusinessPostalCodeFees的BusinessId和BusinessPostalCodeId列中的任何条目都与BusinessPostalCodes表中的条目匹配。如果是这样,那么是的,你可以definitely have a foreign key that references a compound primary key

但是,如果您需要保留BusinessId,我建议您将表格比标准化步骤更进一步。你最终会得到重复的数据。

另外,我建议您不要在SQL中使用货币数据类型:See here.

答案 1 :(得分:0)

最后,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

然后将其添加到您的表格中:

CONSTRAINT [CK_BusinessPostalCodeFees_MatchingBusinessIdPostalCodeAndProfileFeeType] 
CHECK (dbo.MatchingBusinessIdPostalCodeAndProfileFeeType(
    BusinessId, 
    BusinessPostalCodeId, 
    BusinessProfileFeeTypeId) = 1)