首页 > 解决方案 > 列上的 MS SQL 约束

问题描述

我有一个名为 Products 的表,这就是它的样子,我正在尝试在 [IsDefaultProductKey] 列上创建一个约束,只要向其中添加一个值,它就必须是一个活动的产品密钥。

CREATE TABLE [dbo].[Products](
    [ProductId] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](64) NOT NULL,
     [IsActive] [bit] NOT NULL,
    [IsDefaultProductKey] [int] NULL,
CONSTRAINT [PK_dbo.Products] PRIMARY KEY CLUSTERED 
(
    [ProductId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Products] ADD  CONSTRAINT [DF_products_IsActive]  DEFAULT ((1)) FOR [IsActive]
GO
ALTER TABLE [dbo].[Products]  WITH CHECK ADD  CONSTRAINT [FK_Products_Product_IsDefaultProductKey] FOREIGN KEY([IsDefaultProductKey])
REFERENCES [dbo].[Products] ([ProductId])
GO

ALTER TABLE [dbo].[Products] CHECK CONSTRAINT [FK_Products_Product_IsDefaultProductKey]
GO

如果这些是表中的条目,则不应允许第 4 行的值为 1,因为 1 是不活动的。我如何才能为此在表上添加约束

ProductId   Name    IsActive    IsDefaultProductKey
1            Test1  0             NULL
2            Test2  1             NULL
3            Test3  0                2
4            Test4   0             1 (Should not let me do this)

根据建议,我创建了这个 UDF。但仍然没有按照我想要的方式 100% 行事。请提出建议。

CREATE TABLE [dbo].[Products]( [ProductId] [int] IDENTITY(1,1) NOT NULL, 
[Name] [nvarchar](64) NOT NULL, 
[IsActive] [bit] NOT NULL, 
[IsDefaultProductKey] [int] NULL, 
) 
go

Create FUNCTION dbo.CheckProduct (@IsDefaultProductKey int)
RETURNS int
AS 
BEGIN
  DECLARE @retval int
    SELECT @retval = 0
    Select @retval = 1
    FROM [Products]
    WHERE ProductId = @IsDefaultProductKey and IsActive = 1 
  RETURN @retval
END;
GO
--Select CheckProduct(1)

ALTER TABLE [Products] 
  ADD CONSTRAINT chkActiveProduct 
  CHECK (IsDefaultProductKey = null or dbo.CheckProduct(IsDefaultProductKey) = 1); 
go

标签: sql-serverconstraints

解决方案


您可以使用调用 UDF 的 CHECK CONSTRAINT 来查询表以查看所引用的 ProductId 是否处于IsDefaultProductKey活动状态。

编辑:
由于您需要约束来检查两种方式,您将创建一个具有参数的ProductIdUDFIsActiveIsDefaultProductKey

在函数内部,如果 有非 NULL 值IsDefaultProductKey,则需要查询表以查看具有该值的行是否ProductId为 Active。如果不是,则该函数需要返回false

此外,如果IsActive参数传递的值为 0,那么您需要检查表以确保没有行IsDefaultProductKey与参数的值相等ProductId。如果有这样一行,那么函数需要返回false

但如果这两种情况都没有发生,则函数返回true,然后在 CHECK CONSTRAINT 中,您只需测试函数是否返回true


推荐阅读