Multiple foreign key constraints to the same primary key - sql

I have two tables:
Image -> ImageId, ImageBinary (Id is int and auto-incremented)
Customer -> Id, CardImageFront, CardImageBack
Where CardImageFront and CardImageBack are Ids referencing to the ImageId column. The customer will take two pictures of their card: one for the front and one for the back. Both of them will be inserted in the Image table with different ImageId. Now I need tried to add two foreign key constraints on the Customer table (one for CardImageFront and another for CardImageBack) referencing the ImageId column, it says:
Introducing FOREIGN KEY constraint on table 'Customer' may cause cycles or multiple cascade paths
Should only a single foreign key constraint is necessary in this case? Will deleting the CardImageFront from Image table will also delete the CardImageBack? Or is there something wrong with the design?
Code for the Image table:
CREATE TABLE [dbo].[Image](
[Id] [int] IDENTITY(1,1) NOT NULL,
[BinaryImage] [varbinary](8000) NOT NULL,
CONSTRAINT [PK_Image] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
Code for the Customer table:
CREATE TABLE [dbo].[Customer](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](100) NOT NULL,
[ImageFront] [int] NOT NULL,
[ImageBack] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
Code for FK constraints:
ALTER TABLE [dbo].[Customer] WITH CHECK ADD CONSTRAINT [FK_1] FOREIGN KEY([ImageFront])
REFERENCES [dbo].[Image] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Customer] WITH CHECK ADD CONSTRAINT [FK_2] FOREIGN KEY([ImageBack])
REFERENCES [dbo].[Image] ([Id])
ON DELETE CASCADE
GO
Error:
Msg 1785, Level 16, State 0, Line 6
Introducing FOREIGN KEY constraint 'FK_2' on table 'Customer' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Msg 1750, Level 16, State 1, Line 6
Could not create constraint or index. See previous errors.

Related

What is the right way to create relations between these tables in a SQL database?

I have three tables: offices, suboffices, and sales. Each office owns several suboffices, both offices and suboffices sell products. How should I design my sales table to store there office or suboffice where this sale was made?
I was thinking about having a compound foreign key made of office_id and suboffice_id (where suboffice_id may be null, in which case a sale was made in office)
Is it the right way to design a database?
I was also thinking about having two sales tables: for offices and suboffices. But in my opinion it makes things a bit harder..
UPDATE
Sales can be of different types, so they will need different tables. And there will be one table 'SALES' which will store type of a sale and where it was made
Your sub-offices sound the same as your offices from a properties point of view. Here is a diagram of what your table design could look like by having your Office table include a ParentOffice foreign key.
And here is the SQL to create those tables:
CREATE TABLE [dbo].[Office](
[OfficeId] [int] NOT NULL,
[ParentOfficeId] [int] NULL,
[MoreStuff] [nvarchar](50) NULL,
CONSTRAINT [PK_Office] PRIMARY KEY CLUSTERED
(
[OfficeId] 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].[Office] WITH CHECK ADD CONSTRAINT [FK_Office_Office] FOREIGN KEY([ParentOfficeId])
REFERENCES [dbo].[Office] ([OfficeId])
GO
ALTER TABLE [dbo].[Office] CHECK CONSTRAINT [FK_Office_Office]
GO
CREATE TABLE [dbo].[Product](
[ProductId] [int] NOT NULL,
[MoreStuff] [nvarchar](50) NULL,
CONSTRAINT [PK_Product] 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]
CREATE TABLE [dbo].[Sale](
[SaleId] [int] NOT NULL,
[ProducitId] [int] NOT NULL,
[OfficeId] [int] NOT NULL,
CONSTRAINT [PK_Sale] PRIMARY KEY CLUSTERED
(
[SaleId] 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].[Sale] WITH CHECK ADD CONSTRAINT [FK_Sale_Office] FOREIGN KEY([OfficeId])
REFERENCES [dbo].[Office] ([OfficeId])
GO
ALTER TABLE [dbo].[Sale] CHECK CONSTRAINT [FK_Sale_Office]
GO
ALTER TABLE [dbo].[Sale] WITH CHECK ADD CONSTRAINT [FK_Sale_Sale] FOREIGN KEY([ProducitId])
REFERENCES [dbo].[Product] ([ProductId])
GO
ALTER TABLE [dbo].[Sale] CHECK CONSTRAINT [FK_Sale_Sale]
GO
One way to go about this, assuming OFFICE and SUBOFFICE share many of the same attributes is to eliminate the SUBOFFICE table and add a PARENT_OFFICE_ID column to the OFFICE table. Under this design, the distinction between an office and a sub-office would be whether or not PARENT_OFFICE_ID is null. Then SALES can simply have an OFFICE_ID column that can reference either kind of office.

How to set hierarchic foreign key through another table?

I am not sure if my title really explains the question, so I'll try an example:
Let's say I have:
1) region table: parent regions and subregions in the same table (link A)
2) product table: each product is linked to a single parent region (link B)
3) product_price table: lists the price of a product (C) in all sub regions of that product region (link D >>> the link in question).
(the diagram is showing only the relevant fields, there are a lot more data in region and product)
Is there a way to define the region->region_price key, to include only sub_region_id's of the parent_region in the product->region key??
Or, in the terms of the image, how do I make the D link to include only regions that are children [as in A] of the B & C link?
Hope you are getting my point...
Here are the real tables and links:
CREATE TABLE [dbo].[product](
[product_id] [int] NOT NULL,
[product_name] [nchar](10) NOT NULL,
[parent_region_id] [int] NOT NULL,
CONSTRAINT [PK_product] PRIMARY KEY CLUSTERED
(
[product_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[product_price](
[product_id] [int] NOT NULL,
[sub_region_id] [int] NOT NULL,
[price] [decimal](18, 0) NOT NULL,
CONSTRAINT [PK_product_price] PRIMARY KEY CLUSTERED
(
[product_id] ASC,
[sub_region_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[region](
[region_id] [int] NOT NULL,
[region_name] [nvarchar](50) NOT NULL,
[parent_region_id] [int] NULL,
CONSTRAINT [PK_region] PRIMARY KEY CLUSTERED
(
[region_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[product] WITH CHECK ADD CONSTRAINT [FK_product_region] FOREIGN KEY([parent_region_id])
REFERENCES [dbo].[region] ([region_id])
ALTER TABLE [dbo].[product] CHECK CONSTRAINT [FK_product_region]
ALTER TABLE [dbo].[product_price] WITH CHECK ADD CONSTRAINT [FK_product_price_product] FOREIGN KEY([product_id])
REFERENCES [dbo].[product] ([product_id])
ALTER TABLE [dbo].[product_price] CHECK CONSTRAINT [FK_product_price_product]
ALTER TABLE [dbo].[product_price] WITH CHECK ADD CONSTRAINT [FK_product_price_region] FOREIGN KEY([sub_region_id])
REFERENCES [dbo].[region] ([region_id])
ALTER TABLE [dbo].[product_price] CHECK CONSTRAINT [FK_product_price_region]
ALTER TABLE [dbo].[region] WITH CHECK ADD CONSTRAINT [HK_region_region] FOREIGN KEY([parent_region_id])
REFERENCES [dbo].[region] ([region_id])
ALTER TABLE [dbo].[region] CHECK CONSTRAINT [HK_region_region]
I guess you are trying to enforce a business rule with a database rule, but they're not always the same. Instead, you can run validation querys in your code before inserting or updating, or you could implement a trigger that validates your rules or throws an error.

Primary Key error when trying to create Foreign Key

Running into a problem creating a Foreign Key after creating a Parent/Child table scheme with partitioning setup.
CREATE TABLE [dbo].[MessageHeader]
([MessageHeaderID] [int] IDENTITY(1,1) NOT NULL,
[MessageHeaderGlobalId] [uniqueidentifier] NULL,
[CreatedDateTime] [datetime] NOT NULL
)
GO
ALTER TABLE [dbo].[MessageHeader]
ADD CONSTRAINT [PC_MessageHeader_CreatedDateTime_1]
PRIMARY KEY CLUSTERED ([MessageHeaderID], [CreatedDateTime] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = OFF)
ON [PS_Monthly] ([CreatedDatetime])
CREATE TABLE [dbo].[MessageDataInfo]
([MessageDataInfoID] [int] IDENTITY(1,1) NOT NULL,
[MessageHeaderID] [int] NOT NULL,
[CreatedDateTime] [datetime] NOT NULL)
GO
ALTER TABLE [dbo].[MessageDataInfo]
ADD CONSTRAINT [PC__CreatedDateTime_1]
PRIMARY KEY CLUSTERED ([MessageDataInfoID], [CreatedDateTime])
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = OFF)
ON [PS_Monthly] ([CreatedDatetime])
GO
ALTER TABLE [dbo].[MessageDataInfo] WITH CHECK
ADD CONSTRAINT [FK_HeaderID]
FOREIGN KEY([MessageHeaderID])
REFERENCES [dbo].[MessageHeader] ([MessageHeaderID])
What happens is I get the error:
Msg 1776, Level 16, State 0, Line 1
There are no primary or candidate keys in the referenced table 'dbo.MessageHeader' that match the referencing column list in the foreign key 'FK_HeaderID'.
I am not sure why this is happening because that column is obviously the primary key! Any help is appreciated.
You are trying to create a foreign key only on part of Primary key of the parent table. You have to use whole primary key to create a foreign key.
Your foreign key is referencing a single column, but the primary key on MessageHeader is composite. You probably don't mean it to be, so remove CreatedDateTime from the statement that creates the primary key (the first ALTER TABLE one.)

Are foreign key constraints enforced on DELETE when deleting the child?

I want to delete rows on a child table. I receive the error
The DELETE statement conflicted with the REFERENCE constraint
"FK_Address_UserDataSet". The conflict occurred in
database "XYZ", table "dbo.Address", column
'DataSetId'. The statement has been terminated.
I have a database structure with a parent UserDataSet and child Address table (where a parent can have any number of childs).
There is a foreign key constraint (mentioned in the error) that requires the child's DataSetId to relate to a valid UserDataSet.
Here are the table and constraint scripts, created with MS SQL Server Management Studio 2008 in simplified form:
CREATE TABLE [dbo].[Address](
[AddressId] [int] IDENTITY(1,1) NOT NULL,
[DataSetId] [int] NOT NULL,
--other fields
CONSTRAINT [PK_Address] PRIMARY KEY CLUSTERED
(
[AddressId] 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
---
CREATE TABLE [dbo].[UserDataSet](
[DataSetId] [int] IDENTITY(1,1) NOT NULL,
--other fields
CONSTRAINT [PK_UserDataSet] PRIMARY KEY CLUSTERED
(
[DataSetId] 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
---Create the constraint
ALTER TABLE [dbo].[Address] WITH NOCHECK ADD CONSTRAINT [FK_Address_UserDataSet] FOREIGN KEY([DataSetId])
REFERENCES [dbo].[UserDataSet] ([DataSetId])
GO
ALTER TABLE [dbo].[Address] CHECK CONSTRAINT [FK_Address_UserDataSet]
GO
But, how can deleting a child (not the parent) be a problem in this setup?
Can it be that the row to delete is currently invalid, probably added while the constraint was not (yet) in use), an the constraint now is enforced while deleting the child with an invalid foreign key?
Why are you adding the constraint with NOCHECK?
From MSDN documentation...
If you do not want to verify new CHECK or FOREIGN KEY constraints
against existing data, use WITH NOCHECK. We do not recommend doing
this, except in rare cases. The new constraint will be evaluated in
all later data updates. Any constraint violations that are suppressed
by WITH NOCHECK when the constraint is added may cause future updates
to fail if they update rows with data that does not comply with the
constraint.

1:1 table relation can't insert new row

I have a table inheritance in my database. I have table "Item" and Table "Something". Item has ItemId which is primary key and auto increment. In table Something I have ItemId which is primary key (not autoincrement). Theese tables are in 1:1 relation.
So I have tried to insert data in those tables but this doesn't work:
...
DECLARE #itemId int
INSERT INTO dbo.Items
(ItemTypeId,UserId,CreatedOnDate,Title,Description)
VALUES
(#p_ItemTypeId,#p_UserId,#p_CreatedOnDate,#p_Title,#p_Description)
SELECT #itemId = SCOPE_IDENTITY()
INSERT INTO dbo.Something
(ItemsId)
VALUES
(#itemId)
...
This is the error that I get:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Items_Somethings".
Tables create script:
CREATE TABLE [dbo].[Items](
[ItemdId] [int] IDENTITY(1,1) NOT NULL,
[ItemTypeId] [int] NULL,
[UserId] [int] NULL,
[CreatedOnDate] [smalldatetime] NULL,
[Title] [nvarchar](50) NULL,
[Description] [nvarchar](max) NULL,
CONSTRAINT [PK_Items] PRIMARY KEY CLUSTERED
(
[ItemId] 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].[Items] WITH CHECK ADD CONSTRAINT [FK_Items_Somethings] FOREIGN KEY([ItemId])
REFERENCES [dbo].[Somethings] ([ItemId])
GO
ALTER TABLE [dbo].[Items] CHECK CONSTRAINT [FK_Items_Somethings]
GO
CREATE TABLE [dbo].[Somethings](
[ItemId] [int] NOT NULL,
CONSTRAINT [PK_Somethings] PRIMARY KEY CLUSTERED
(
[ItemId] 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].[Items] WITH CHECK ADD CONSTRAINT [FK_Items_Somethings] FOREIGN KEY([ItemId])
REFERENCES [dbo].[Somethings] ([ItemId])
Bad Direction of foreign key.
You should add foreign key to [dbo].[Somethings] and reference [dbo].[Items].ItemId
Like this:
ALTER TABLE [dbo].[Somethings] WITH CHECK ADD CONSTRAINT [FK_Somethings_Items] FOREIGN KEY([ItemId])
REFERENCES [dbo].[Items] ([ItemId])
In this script, you have inverted the inheritance between the tables. If Something table inherits from Item table then the FK has to be created at Table `Something' like this :
ALTER TABLE [dbo].[Somethings] WITH CHECK ADD CONSTRAINT [FK_Somethings_Items] FOREIGN KEY([ItemId])
REFERENCES [dbo].[Items] ([ItemId])
GO
ALTER TABLE [dbo].[Somethings] CHECK CONSTRAINT [FK_Somethings_Items]
GO