简体   繁体   English

引用外键并为父表中的列添加检查约束

[英]Reference a foreign key and Add check constraint for column in parent table

How can I Add to the Table BusinessCategories a check that the column IsBusinessCategory value is 'true' for the related Categories.ID ?如何向表BusinessCategories添加检查列IsBusinessCategory值是否为相关Categories.ID “true”?

CREATE TABLE [dbo].[Categories](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [ParentID] [int] NULL,
    [DisplayNameHe] [nvarchar](400) NOT NULL,
    [DisplayNameEn] [nvarchar](400) NOT NULL,
    [DisplayNameEs] [nvarchar](400) NOT NULL,
    [CreateDate] [datetime] NOT NULL,
    [Status] [bit] NOT NULL,
    [IsBusinessCategory] [bit] NULL
)



CREATE TABLE [dbo].[BusinessCategories](
    [ID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [BusinessCategoryID] [INT] NOT NULL REFERENCES Categories(ID) -- Need to check that is 
     businessCategory ==1
    [BusinessID] [INT] NOT NULL REFERENCES Business(ID)
)

The goal is to be able to insert to the column BusinessCategoryID only values from Categories table that has IsBusinessCategory == true .目标是能够仅将具有IsBusinessCategory == true 的Categories表中的值插入到列BusinessCategoryID 中

I don't recommend that kind of solution, that should be done in the application's business layer我不推荐那种解决方案,应该在应用程序的业务层完成

In SQL side there is a tricky way, not optimal, but doable...在 SQL 方面有一个棘手的方法,不是最佳的,但可行的......

First create an scalar function that returns the isBusinessCategory value of the selected category首先创建一个标量函数,返回所选类别的 isBusinessCategory 值

CREATE FUNCTION fn_isBusinessCategory (@CatID INT) RETURNS INT
AS
BEGIN
    RETURN (SELECT isBusinessCategory FROM Categories WHERE CategoryID = @CatID)
END
GO

Create another scalar function that returns 1 if a given category is referenced in BusinessCategories创建另一个标量函数,如果在 BusinessCategories 中引用给定类别,则该函数返回 1

CREATE FUNCTION fn_isBusinessCategoryValid (@CatID INT, @isBusinessCat BIT) RETURNS BIT
AS
BEGIN
    IF @isBusinessCat = 1
        RETURN 1
    ELSE IF EXISTS (SELECT 1 FROM BusinessCategories WHERE CategoryID = @CatID)
        RETURN 0
    ELSE
        RETURN 1
END
GO

Add the following constraints添加以下约束

Step 1 Foreign key to validate integrity between two tables步骤 1 验证两个表之间完整性的外键

ALTER TABLE BusinessCategories ADD CONSTRAINT FK_BusinessCategory 
FOREIGN KEY (CategoryID) 
REFERENCES Categories (CategoryID)

Step 2 Check constraint to validate that category is_businessCategory步骤 2 检查约束以验证该类别 is_businessCategory

ALTER TABLE BusinessCategories ADD CONSTRAINT ck_BusinessCategory 
CHECK (dbo.fn_isBusinessCategory(CategoryID) = 1)

Step 3 Check constraint to prevent a category to be changed as non businessCategory when is used步骤 3 检查约束以防止使用时将类别更改为非业务类别

ALTER TABLE Categories ADD CONSTRAINT ck_Category_isBusinessCategory 
CHECK (dbo.fn_isBusinessCategoryValid(CategoryID, isBusinessCategory) = 1)

The goal is to be able to insert to the column BusinessCategoryID only values from Categories table that has IsBusinessCategory == true.目标是能够仅将具有 IsBusinessCategory == true 的 Categories 表中的值插入到列 BusinessCategoryID。

You can do this much by writing a UDF that takes BusinessCategoryID as a parameter and queries the Categories table to get the value of IsBusinessCategory .您可以通过编写一个将BusinessCategoryID作为参数并查询 Categories 表以获取IsBusinessCategory的值的 UDF 来实现这IsBusinessCategory The CHECK constraint would simply test whether the returned value of the parameter is true or false. CHECK 约束将简单地测试参数的返回值是真还是假。

Be warned however, that this constraint will only be checked when you add rows to the BusinessCategories table.但是请注意,只有在向BusinessCategories表添加行时才会检查此约束。 If someone changes the value of IsBusinessCategory in the Categories table, the CHECK constraint will not catch it.如果有人更改了Categories表中IsBusinessCategory的值,则 CHECK 约束将无法捕获它。 You would need to put a separate constraint on the Categories table to catch that.您需要在Categories表上放置一个单独的约束来捕捉它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM