I got table "Functions" with Function_ID {PK} and I want another table "Hierarchy" with Hierarchy_ID {PK} which defines tree structure of functions so i need one Function_ID from Function table AS Parent_ID and one Function_ID AS Child. my question is how i can use two primary keys from another table to make it together as Foreign key
I am using SQL Server 2012 and the Management Studio
Many Thanks
Actually you just need to add a ParentFunction_ID column in the Functions table.
You don't need another table if your structure is indeed a tree.
Then make the ParentFunction_ID to be a FK to the same table Functions.
So ParentFunction_ID (FK) would be pointing to Function_ID (PK).
The only record which has ParentFunction_ID NULL would be the root of your tree.
Here is some sample code:
USE [test]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Functions](
[Function_ID] [int] IDENTITY(1,1) NOT NULL,
[FunctionCode] [varchar](max) NULL,
[ParentFunction_ID] [int] NULL,
CONSTRAINT [PK_Functions] PRIMARY KEY CLUSTERED
(
[Function_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]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[Functions] WITH CHECK ADD CONSTRAINT [FK_Functions_Functions] FOREIGN KEY([ParentFunction_ID])
REFERENCES [dbo].[Functions] ([Function_ID])
GO
ALTER TABLE [dbo].[Functions] CHECK CONSTRAINT [FK_Functions_Functions]
GO
Name your Functions table a Function table. AFAIK using
plurals for table names is not really a good practice.
So you can do this.
--- 1 ---
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Function](
[Function_ID] [int] IDENTITY(1,1) NOT NULL,
[FunctionCode] [varchar](max) NULL,
CONSTRAINT [PK_Function] PRIMARY KEY CLUSTERED
(
[Function_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]
GO
SET ANSI_PADDING OFF
GO
--- 2 ---
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Hierarchy](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ParentFunction_ID] [int] NULL,
[ChildFunction_ID] [int] NULL,
CONSTRAINT [PK_Hierarchy] PRIMARY KEY CLUSTERED
(
[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]
GO
ALTER TABLE [dbo].[Hierarchy] WITH CHECK ADD CONSTRAINT [FK_Hierarchy_Function] FOREIGN KEY([ParentFunction_ID])
REFERENCES [dbo].[Function] ([Function_ID])
GO
ALTER TABLE [dbo].[Hierarchy] CHECK CONSTRAINT [FK_Hierarchy_Function]
GO
ALTER TABLE [dbo].[Hierarchy] WITH CHECK ADD CONSTRAINT [FK_Hierarchy_Function1] FOREIGN KEY([ChildFunction_ID])
REFERENCES [dbo].[Function] ([Function_ID])
GO
ALTER TABLE [dbo].[Hierarchy] CHECK CONSTRAINT [FK_Hierarchy_Function1]
GO
Related
In SQL Server I have a simple database schema, where Authors and Books have a many-many join table, and both have foreign keys to Publishers.
I am not allowed to set ON CASCADE DELETE on all the relations:
Unable to create relationship 'FK_Books_Publishers'.
Introducing FOREIGN KEY constraint 'FK_Books_Publishers' on table 'Books' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.
What's the cycle here? Don't cascade cycles end at join tables as they have no foreign keys referencing them?
Or is it that deleting a Publisher may give two causes for deleting a BookAuthor row (via Authors or via Books)? And why would that be a problem?
This is the DDL for the above:
USE [fk-test]
GO
/****** Object: Table [dbo].[Authors] Script Date: 3-6-2022 15:23:22 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Authors](
[Id] [int] NOT NULL,
[PublisherId] [int] NOT NULL,
[Name] [nvarchar](50) NULL,
CONSTRAINT [PK_Authors] 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
/****** Object: Table [dbo].[BookAuthor] Script Date: 3-6-2022 15:23:22 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[BookAuthor](
[BookId] [int] NOT NULL,
[AuthorId] [int] NOT NULL
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[Books] Script Date: 3-6-2022 15:23:22 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Books](
[Id] [int] NOT NULL,
[PublisherId] [int] NOT NULL,
[Title] [nchar](50) NULL,
CONSTRAINT [PK_Books] 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
/****** Object: Table [dbo].[Publishers] Script Date: 3-6-2022 15:23:22 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Publishers](
[Id] [int] NOT NULL,
[Name] [nvarchar](50) NULL,
CONSTRAINT [PK_Publishers] 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
ALTER TABLE [dbo].[Authors] WITH CHECK ADD CONSTRAINT [FK_Authors_Authors] FOREIGN KEY([PublisherId])
REFERENCES [dbo].[Publishers] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Authors] CHECK CONSTRAINT [FK_Authors_Authors]
GO
ALTER TABLE [dbo].[BookAuthor] WITH CHECK ADD CONSTRAINT [FK_BookAuthor_Authors] FOREIGN KEY([AuthorId])
REFERENCES [dbo].[Authors] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[BookAuthor] CHECK CONSTRAINT [FK_BookAuthor_Authors]
GO
ALTER TABLE [dbo].[BookAuthor] WITH CHECK ADD CONSTRAINT [FK_BookAuthor_Books] FOREIGN KEY([BookId])
REFERENCES [dbo].[Books] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[BookAuthor] CHECK CONSTRAINT [FK_BookAuthor_Books]
GO
ALTER TABLE [dbo].[Books] WITH CHECK ADD CONSTRAINT [FK_Books_Publishers] FOREIGN KEY([PublisherId])
REFERENCES [dbo].[Publishers] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Books] CHECK CONSTRAINT [FK_Books_Publishers]
GO
It's because there'd be two cascading delete paths from Publisher to BookAuthor,one via Author and one via Books.
A solutions is to modify the two foreign keys
FK_Authors_Authors
FK_Books_Publishers
to
ON DELETE SET NULL
And make PublisherId in Books and Authors nullable.
Then you'll need to do your own custom cascade delete code when deleting a publisher. e.g delete the publisher, then delete the relevant Authors and Books.
I need to add a new foreign key to my table called starList. It currently does not have a foreign key relationship with the table called planetList.
So I ran this command:
ALTER TABLE [dbo].[starList] WITH CHECK
ADD CONSTRAINT [FK_starList_planetList]
FOREIGN KEY([planetId]) REFERENCES [dbo].[planetList] ([planetId])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
But I get this error:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_starList_planetList".
The conflict occurred in database "astro101", table "dbo.planetList", column 'planetID'.
I am not sure what that means.
I tried looking around my tables on SQL Server but I don't see anything wrong.
Could anyone help me figure out what the error means?
Thanks!
My starList table looks like this:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[starList]
(
[starID] [nvarchar](50) NOT NULL,
[galaxyID] [uniqueidentifier] NOT NULL,
[starTitle] [nvarchar](3000) NULL,
[planetID] [uniqueidentifier] NULL,
CONSTRAINT [PK_StarList]
PRIMARY KEY CLUSTERED ([starID] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[starList] WITH CHECK
ADD CONSTRAINT [FK_starList_galaxyList]
FOREIGN KEY([galaxyID]) REFERENCES [dbo].[galaxyList] ([galaxyID])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[starList] CHECK CONSTRAINT [FK_starList_galaxyList]
GO
And the planetList table is this:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[planetList]
(
[planetID] [uniqueidentifier] NOT NULL,
[planetText] [nvarchar](max) NULL,
PRIMARY KEY CLUSTERED ([planetID] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
You need to check your data in both columns.
There is a value in the column of foreign key table whose associated value doesn't exist in the primary key table.
You have data in starlist.planetid which does not match/correspond to planetlist.planetid.
Both of them need to be the same with values values. It would be better to truncate them and then try creating the contraint.
In short, there is violation of referential integrity rules.
If this is the case, keep in mind to create foreign key before populating the tables.
I am trying to create replica of my database from SQL server to another.
For that I am generating script from original server and trying to run in another server. I've created database manually with the same name.
Here is the screenshot of original database
When I generate script, following script is created which I am trying in another server
USE [ContactsApp]
GO
/****** Object: Table [common].[BU] Script Date: 2/12/2016 3:02:29 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [common].[BU](
[ID] [int] IDENTITY(1,1) NOT NULL,
[IndustryID] [int] NOT NULL,
[BU] [varchar](50) NOT NULL,
[Code] [varchar](2) NOT NULL,
[Active] [bit] NOT NULL,
[CreatedBy] [uniqueidentifier] NOT NULL,
[CreateDate] [date] NOT NULL,
[CreateTime] [time](3) NOT NULL,
[ModifiedBy] [uniqueidentifier] NULL,
[ModifyDate] [date] NULL,
[ModifyTime] [time](3) NULL,
CONSTRAINT [PK_BU] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [UK_BU_Code] UNIQUE NONCLUSTERED
(
[Code] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [UK_BU_Name] UNIQUE NONCLUSTERED
(
[BU] 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
SET ANSI_PADDING OFF
GO
ALTER TABLE [common].[BU] ADD CONSTRAINT [DF_BU_CreateDate] DEFAULT (CONVERT([date],getdate())) FOR [CreateDate]
GO
ALTER TABLE [common].[BU] ADD CONSTRAINT [DF_BU_CreateTime] DEFAULT (CONVERT([time],getdate())) FOR [CreateTime]
GO
ALTER TABLE [common].[BU] WITH CHECK ADD CONSTRAINT [FK_BU_Industry] FOREIGN KEY([IndustryID])
REFERENCES [common].[Industry] ([ID])
ON DELETE CASCADE
GO
ALTER TABLE [common].[BU] CHECK CONSTRAINT [FK_BU_Industry]
GO
When I try to run this script, I get following error
The specified schema name "common" either does not exist or you do
not have permission to use it.
I don't know what is the meaning of common here.Thanks
Your tables are 'grouped' (for want of better word) in schemas (google for it). You should run
CREATE SCHEMA common
And likewise for all other schemas.
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.
I have three tables a,b,and c each with an int IDENTITY PK field that relates to the child table.
CREATE TABLE [dbo].[a]([aID] [int] IDENTITY(1,1) NOT NULL,[aCode] [varchar](20) NOT NULL,
CONSTRAINT [PK_a] PRIMARY KEY CLUSTERED([aID] 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].[b]([bID] [int] IDENTITY(1,1) NOT NULL,[aID] [int] NOT NULL, [bCode] [varchar](20) NOT NULL,
CONSTRAINT [PK_b] PRIMARY KEY CLUSTERED([bID] 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].[c]([cID] [int] IDENTITY(1,1) NOT NULL,[bID] [int] NOT NULL,[cCode] [varchar](20) NOT NULL,
CONSTRAINT [PK_c] PRIMARY KEY CLUSTERED([cID] 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].[b] WITH CHECK ADD CONSTRAINT [FK_b_a] FOREIGN KEY([aID])
REFERENCES [dbo].[a] ([aID])
GO
ALTER TABLE [dbo].[b] CHECK CONSTRAINT [FK_b_a]
GO
ALTER TABLE [dbo].[c] WITH CHECK ADD CONSTRAINT [FK_c_b] FOREIGN KEY([bID])
REFERENCES [dbo].[b] ([bID])
GO
ALTER TABLE [dbo].[c] CHECK CONSTRAINT [FK_c_b]
GO
How do I create a CONSTRAINT that enforces a unique condition for a.aID, c.cCode?
If you are looking for a unique constraint over a combination of columns a.aID, c.cCode one way is to alter table c and add [aid] column to it and have a composite unique key.
ALTER TABLE [dbo].[c](
[cID] [int] IDENTITY(1,1) NOT NULL,
[bID] [int] NOT NULL,[cCode] [varchar](20) NOT NULL,
[cCode] [varchar](20) NOT NULL,
[aID] INT FOREIGN KEY REFERENCES [a]([aID]) NOT NULL,
CONSTRAINT uq_cCode_aid UNIQUE NONCLUSTERED (cCode,aID),
CONSTRAINT [PK_c] PRIMARY KEY CLUSTERED([cID] 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
You can add a unique constraint as follows:
ALTER TABLE [C] ADD CONSTRAINT [uc_C_cCode] UNIQUE NONCLUSTERED [cCode];
You cannot however enforce a constraint across tables, which is what it sounds like you are trying to do.
As for table A.aID, its a primary key, it will already have a unique constraint.
I found a way to get what I wanted (I think) using an indexed view. Please comment on if this seems appropriate. My tests so far conclude that it does work.
I created a view with schemabinding on joining c to a (going through b).
I created an clustered index to enforce unique on aID and cCode.
This allows me to not need to include aID within the c table but still enforces the unique constraint.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW [dbo].[vw.aIDcCode] WITH SCHEMABINDING
AS
SELECT dbo.a.aID, dbo.c.cCode
FROM dbo.a
INNER JOIN
dbo.b ON dbo.a.aID = dbo.b.aID
INNER JOIN
dbo.c ON dbo.b.bID = dbo.c.bID
GO
SET ARITHABORT ON
GO
SET CONCAT_NULL_YIELDS_NULL ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
SET ANSI_PADDING ON
GO
SET ANSI_WARNINGS ON
GO
SET NUMERIC_ROUNDABORT OFF
GO
CREATE UNIQUE CLUSTERED INDEX [IDX_Unique_aIDcCode] ON [dbo].[vw.aIDcCode]
([aID] ASC, [cCode] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY]
GO