我有一个数据库,有两个表Ads
和Images
。 adid
表中有一个主键Ads
,它是Images
表中的外键。
我想在表Images
上创建一个约束,adid
表中可以存储不超过5 Images
。
我需要知道调用这种类型的约束以及如何使用SQL Server中的查询来完成此操作。
答案 0 :(得分:3)
没有constaint来强制执行该规则,但是像下面这样的触发器可以执行:
CREATE TRIGGER Images_not_more_than_five_per_add
ON Images FOR INSERT
AS
DECLARE @RowCount int
SET @RowCount = @@ROWCOUNT
SET NOCOUNT ON
IF @RowCount = 1
BEGIN
IF (SELECT COUNT(*) FROM Images WHERE Images.addid = (SELECT addid FROM inserted)) > 5
BEGIN
RAISERROR('No more than five images per add are allowed', 16, -1)
ROLLBACK
RETURN
END
END
ELSE
BEGIN
IF EXISTS (
SELECT *
FROM
Images
INNER JOIN (
SELECT DISTINCT addid FROM inserted
) I ON Images.addid = I.addid
GROUP BY
Images.addid
HAVING COUNT(*) > 5
)
BEGIN
RAISERROR('No more than five images per add are allowed', 16, -1)
ROLLBACK
RETURN
END
END
答案 1 :(得分:0)
外键约束没有限制子行数的选项。
使用触发器可以实现期望的效果,但是这种约束相对简单,并且可以仅使用声明性约束来实现期望的效果。
创建一个帮助表CheckFiveRows
,其列ID
包含五行,值为1到5. ID
是主键。确保它只包含五行。将列CheckFiveRowID
添加到Images
表,该表是指向CheckFiveRows.ID
的外键。在(AdID, CheckFiveRowID)
上添加唯一约束/索引。
表广告
CREATE TABLE [dbo].[Ads](
[AdID] [int] NOT NULL,
[AdData] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Ads] PRIMARY KEY CLUSTERED
(
[AdID] ASC
))
表格CheckFiveRows
CREATE TABLE [dbo].[CheckFiveRows](
[ID] [int] NOT NULL,
CONSTRAINT [PK_CheckFiveRows] PRIMARY KEY CLUSTERED
(
[ID] ASC
))
GO
INSERT INTO [dbo].[CheckFiveRows] ([ID]) VALUES
(1),(2),(3),(4),(5);
表格图片
CREATE TABLE [dbo].[Images](
[ImageID] [int] NOT NULL,
[AdID] [int] NOT NULL,
[CheckFiveRowID] [int] NOT NULL,
[ImageData] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Images] PRIMARY KEY CLUSTERED
(
[ImageID] ASC
))
GO
ALTER TABLE [dbo].[Images] WITH CHECK
ADD CONSTRAINT [FK_Images_Ads] FOREIGN KEY([AdID])
REFERENCES [dbo].[Ads] ([AdID])
GO
ALTER TABLE [dbo].[Images] CHECK CONSTRAINT [FK_Images_Ads]
GO
ALTER TABLE [dbo].[Images] WITH CHECK
ADD CONSTRAINT [FK_Images_CheckFiveRows] FOREIGN KEY([CheckFiveRowID])
REFERENCES [dbo].[CheckFiveRows] ([ID])
GO
ALTER TABLE [dbo].[Images] CHECK CONSTRAINT [FK_Images_CheckFiveRows]
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_CheckFiveRows] ON [dbo].[Images]
(
[AdID] ASC,
[CheckFiveRowID] ASC
)
GO
<强>测试强>
填充Ads
:
INSERT INTO [dbo].[Ads] ([AdID],[AdData]) VALUES
(1, 'a1'),
(2, 'a2');
(2 row(s) affected)
填充Images
:
INSERT INTO [dbo].[Images] ([ImageID],[AdID],[CheckFiveRowID],[ImageData]) VALUES
(1,1,1,'i1'),
(2,1,2,'i2'),
(3,1,3,'i3'),
(4,1,4,'i4');
(4 row(s) affected)
尝试为AdID=1
添加另外两行:
INSERT INTO [dbo].[Images] ([ImageID],[AdID],[CheckFiveRowID],[ImageData]) VALUES
(5,1,5,'i5'),
(6,1,5,'i6');
Msg 2601, Level 14, State 1, Line 8
Cannot insert duplicate key row in object 'dbo.Images' with unique index 'IX_CheckFiveRows'. The duplicate key value is (1, 5).
The statement has been terminated.
尝试为AdID=2
插入6行:
INSERT INTO [dbo].[Images] ([ImageID],[AdID],[CheckFiveRowID],[ImageData]) VALUES
(11,2,1,'i1'),
(12,2,2,'i2'),
(13,2,3,'i3'),
(14,2,4,'i4'),
(15,2,5,'i5'),
(16,2,6,'i6');
Msg 547, Level 16, State 0, Line 13
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Images_CheckFiveRows". The conflict occurred in database "AdventureWorks2014", table "dbo.CheckFiveRows", column 'ID'.
The statement has been terminated.