I have a database and there are two tables Ads
and Images
. There is a primary key adid
in Ads
table which is a foreign ke
The foreign key constraint doesn't have such option to limit the number of child rows.
It is possible to achieve the desired effect using a trigger, but this kind of constraint is relatively simple and it is possible to achieve the desired effect using only declarative constraints.
Create a helper table CheckFiveRows
with column ID
that contains five rows with values 1 to 5. ID
is the primary key. Make sure that it contains only five rows. Add a column CheckFiveRowID
to the Images
table that is a foreign key pointing to CheckFiveRows.ID
. Add unique constraint/index on (AdID, CheckFiveRowID)
.
Table Ads
CREATE TABLE [dbo].[Ads](
[AdID] [int] NOT NULL,
[AdData] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Ads] PRIMARY KEY CLUSTERED
(
[AdID] ASC
))
Table 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);
Table Images
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
Testing
Populate Ads
:
INSERT INTO [dbo].[Ads] ([AdID],[AdData]) VALUES
(1, 'a1'),
(2, 'a2');
(2 row(s) affected)
Populate 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)
Try to add two more row for 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.
Try to insert 6 rows for AdID=2
:
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.