基本上我们说我有一个" 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
,但我更愿意保留这个专栏并保证它们是相同的。我有什么可以做的吗?
答案 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)