在我们的零售系统中,我们计划将购物篮信息从浏览器Cookie移至表格。我们目前在C#应用程序中实现了篮子的限制,但如果可能的话,希望将该业务逻辑作为约束向下移动到数据库。
CREATE TABLE [dbo].[BasketProduct](
[BasketProductId] [int] IDENTITY(1,1) NOT NULL,
[BasketId] [int] NOT NULL,
[ProductId] [int] NOT NULL,
[Quantity] [int] NOT NULL,
CONSTRAINT [PK_BasketProduct] PRIMARY KEY CLUSTERED
([BasketProductId] ASC))
我们希望限制每个购物篮最多包含10个唯一商品,但每个商品都允许有任意数量,因此,篮子ID值在表格中最多只能显示10次。
似乎似乎没有明显的约束,因为在计算列中不允许包括窗口函数的聚合。
有人可以推荐合适的方法吗?
这不理想,但是正如我在评论中提到的,我将在执行INSERT
/UPDATE
/ DELETE
的SP中处理此问题(不太可能需要DELETE
)。因此,对于INSERT
,您将具有如下所示的内容:
USE Sandbox;
GO
CREATE TABLE [dbo].[BasketProduct](
[BasketProductId] [int] IDENTITY(1,1) NOT NULL,
[BasketId] [int] NOT NULL,
[ProductId] [int] NOT NULL,
[Quantity] [int] NOT NULL,
CONSTRAINT [PK_BasketProduct] PRIMARY KEY CLUSTERED
([BasketProductId] ASC));
GO
CREATE PROC AddBasketProduct @BasketID int, @ProductID int, @Quantity int AS
BEGIN
DECLARE @DistinctProducts int;
SELECT @DistinctProducts = COUNT(DISTINCT ProductID)
FROM dbo.BasketProduct WITH (UPDLOCK) --As we need to control concurrency issues
WHERE BasketId = @BasketID
AND ProductID != @ProductID ;
IF @DistinctProducts >= 10
THROW 71245, N'Cannot have more than 10 different products in a single basket.',16; --Choose an error number and state appropraite for your applciation
ELSE
INSERT INTO dbo.BasketProduct (BasketId,
ProductId,
Quantity)
VALUES(@BasketID,@ProductID,@Quantity);
END;
GO
--Make some sample data
INSERT INTO dbo.BasketProduct (BasketId,
ProductId,
Quantity)
VALUES(1,1,1),
(1,2,1),
(1,3,1),
(1,4,1),
(1,5,1),
(1,6,1),
(1,7,1),
(1,8,1),
(1,9,1),
(1,10,1); --10 products.
GO
--11th product, will fail
EXEC dbo.AddBasketProduct @BasketID = 1,
@ProductID = 11,
@Quantity = 1;
GO
--Repetition of product 2, will work
EXEC dbo.AddBasketProduct @BasketID = 1,
@ProductID = 2,
@Quantity = 1;
GO
DROP PROC dbo.AddBasketProduct;
DROP TABLE dbo.BasketProduct;
请不要这样做,表定义中的函数会导致各种问题...
但是作为我上面评论的补充,这将满足您的要求
但是请不要这样做
use tempdb;
DROP TABLE IF EXISTS CheckTbl
CREATE TABLE CheckTbl (col1 int);
GO
CREATE OR ALTER FUNCTION CheckCount(@tocheck int)
RETURNS int
AS
BEGIN
DECLARE @return INTEGER = (select count(*) from CheckTbl where col1 = @tocheck);
return @return;
END;
GO
ALTER TABLE CheckTbl
ADD CONSTRAINT chkRowCount CHECK (dbo.CheckCount(col1) <= 2 );
GO
INSERT INTO CheckTbl VALUES(1) -- allowed
INSERT INTO CheckTbl VALUES(2) -- allowed
INSERT INTO CheckTbl VALUES(1) -- allowed
INSERT INTO CheckTbl VALUES(2) -- allowed
INSERT INTO CheckTbl VALUES(1) -- NOT allowed
另请参阅Custom function with check constraint SQL Server 2008,以使用适合这种情况的索引视图解决方案