I have a table with two columns as the primary key. These two columns are also a foreign key that references the same table:
(This table was created some time ago by someone who has since left the company)
CREATE TABLE [dbo].[tblItemLink](
[ItemListID] [int] NOT NULL,
[ItemID] [int] NOT NULL,
CONSTRAINT [PK_tblItemList] PRIMARY KEY CLUSTERED
(
[ItemListID] ASC,
[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].[tblItemLink] WITH CHECK ADD CONSTRAINT [FK_tblItemLink_tblItemLink] FOREIGN KEY([ItemListID], [ItemID])
REFERENCES [dbo].[tblItemLink] ([ItemListID], [ItemID])
GO
ALTER TABLE [dbo].[tblItemLink] CHECK CONSTRAINT [FK_tblItemLink_tblItemLink]
GO
In practice, ItemID refers to tblItem.ItemID, and ItemListID is found nowhere else in the DB but there is a corresponding enum in the application.
Is there any reason for the primary key to also be a foreign key referencing itself (ie. some undocumented performance improvement), or is it just a mistake?
I know of no reason why this, specifically, could provide a benefit - so I'm going to go with option 2 - a mistake.
Of course, if it was different columns in the same table, that would make sense, and as #Jignesh.Raj points out, that would form some kind of hierarchy.
You can even sometimes end up with multiple hierarchies within the same table with such multi-column references:
CREATE TABLE T (
GroupID int not null,
ItemID int not null,
ParentItemID int null,
constraint PK_T PRIMARY KEY (GroupID,ItemID),
constraint FK_T_Parent FOREIGN KEY (GroupID,ParentItemID) references T (GroupID,ItemID)
)
In the above, the GroupID column always references itself.
But as I say, with your current table, where both columns only reference themselves, it makes no sense.
Thats how you would create a hierarchy, and could also ensure you can't have a child with an invalid parent.
See also Should you make a self-referencing table column a foreign key?
Related
In my job, checking the database diagrams I have found a One-to-one relation between two tables, but the relation is not between two primary keys, the relation is between a primary key in one table and other non primary key attribute in the other table. In the database diagrams appear as "One to One relation". I wonder how can I create this kind of relationship "One to One" using just one primary on one table and using a non primary key in the other table.
Here are the scripts for "create" that I found in the database
---------------To create table Agreement Documents--------------
CREATE TABLE [dbo].[AgreementDocuments](
[AgreementDocumentID] [int] IDENTITY(1,1) NOT NULL,
[AgreementID] [int] NOT NULL,
[Document] [varbinary](max) NOT NULL,
CONSTRAINT [PK_AgreementDocuments] PRIMARY KEY CLUSTERED
([AgreementDocumentID] 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]
ALTER TABLE [dbo].[AgreementDocuments] WITH CHECK ADD CONSTRAINT
[FK_AgreementDocuments_Agreements] FOREIGN KEY([AgreementID])
REFERENCES [dbo].[Agreements] ([AgreementID])
GO
ALTER TABLE [dbo].[AgreementDocuments] CHECK CONSTRAINT
[FK_AgreementDocuments_Agreements]
GO
--------------------------To create table Agreements-----------------------
CREATE TABLE [dbo].[Agreements](
[AgreementID] [int] IDENTITY(1,1) NOT NULL,
[ContactID] [int] NOT NULL,
[ClientID] [int] NOT NULL,
CONSTRAINT [PK_Agreements] PRIMARY KEY CLUSTERED
([AgreementID] 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
If I run this two queries in a separate database, it creates two tables with "One to Many" relation. How is that possible?
You can make this a one-to-one relationship by adding a UNIQUE CONSTRAINT to the AgreementID field:
ALTER TABLE dbo.AgreementDocuments
ADD CONSTRAINT uq_AgreementDocuments_AgreementId UNIQUE (AgreementId)
With the unique constraint, it will force it to be a one-to-one, rather than a one-to-many:
Before Constraint:
After Constraint:
Create table one with an identifying ID column.
AgreementDocumentID is identity and distinct
In the other table do a foreign key to the first table AgreementDocumentID field. And then put a distinct index on the second table for AgreementDocumentID.
If I understand your question.
No Er-Digram tool works 100% you have to edit what they create to make it right. Depending on the tool quality your amount of edits change.
I am taking an introductory course on SQL and I'm stumped on one of our labs. For this lab, we get an ERD that we need to implement via SQL. The lab requires us to create two tables joined together with an associative table (SQL apparently doesn't like many to many relationships).
In this associative table, both attributes need to be primary keys and foreign keys (Pk, Fk) according the ERD. This doesn't make much sense to me (you can't have multiple primary keys) and thus have far I have been unable to implement the ERD by creating multiple primary keys in the table. Where I am going wrong here internet?
The code:
CREATE Table dbo.TargetMailingList
(
TargetID INT NOT Null
Foreign Key References dbo.TargetCustomers(TargetID),
MailingListsID INT Not NULL
Foreign Key References dbo.Mailinglists(MailingListID),
Primary Key (MailingListID,TargetID),
);
There are no two primary keys. It is a compound key. Both the columns are part of the same primary key. Check out http://en.wikipedia.org/wiki/Compound_key for more info.
You can create a compound key, as stated by #Juru and create 2 foreign keys:
CREATE TABLE dbo.Table_link
(
ndIdTable1 int NOT NULL,
ndIdTable2 int NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Table_link ADD CONSTRAINT
PK_Table_link PRIMARY KEY CLUSTERED
(
ndIdTable1,
ndIdTable2
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ALTER TABLE dbo.Table_link ADD CONSTRAINT
FK_Table_Table_1 FOREIGN KEY
(
ndIdTable1
) REFERENCES dbo.Table_1
(
ndIdTable1
) ON UPDATE NO ACTION
ON DELETE NO ACTION
GO
ALTER TABLE dbo.Table_link ADD CONSTRAINT
FK_Table_Table_2 FOREIGN KEY
(
ndIdTable1
) REFERENCES dbo.Table_2
(
ndIdTable2
) ON UPDATE NO ACTION
ON DELETE NO ACTION
GO
I have one member table structure in SQL Server:
member_table
memberid name address email
111 aaa IND a#a.com
222 bbb UK b#b.com
Now I want to give such facility that one member can follow as many other members. How can I do that?
Should I create a new table? Should I use any flags?
I'm thiking to create a new table and give Member table
You can create another table consisting of two attributes (member_id, follows_member_id)
This table keeps records of each member following other members. Both attributes reference your members table. This is a standard approach in creating a many-many relation as it is normalized. read more
I would create a junction table with a key on both member_ids to ensure there is at most 1 row.
I try to not cater to YGWITs (your gonna want it), but it seems a subscription table would call for some additional metadata such as the date the subscription starts or the last access date to know if there is new activity.
I would end up with something like this:
CREATE TABLE [dbo].[member_subscription](
[member_id] [int] NOT NULL,
[target_member_id] [int] NOT NULL,
[date_created] [datetime] NOT NULL,
[date_last_visit] [datetime] NULL,
CONSTRAINT [PK_member_subscription] PRIMARY KEY CLUSTERED
( -- key on both member_id fields
[member_id] ASC,
[target_member_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
-- Foreign key contrain for member_id
ALTER TABLE [dbo].[member_subscription] WITH CHECK ADD CONSTRAINT [FK_member_subscription_member] FOREIGN KEY([member_id])
REFERENCES [dbo].[member] ([member_id])
GO
ALTER TABLE [dbo].[member_subscription] CHECK CONSTRAINT [FK_member_subscription_member]
GO
-- Foreign key contrain for target_member_id
ALTER TABLE [dbo].[member_subscription] WITH CHECK ADD CONSTRAINT [FK_member_subscription_target_member] FOREIGN KEY([target_member_id])
REFERENCES [dbo].[member] ([member_id])
GO
ALTER TABLE [dbo].[member_subscription] CHECK CONSTRAINT [FK_member_subscription_target_member]
GO
-- Default value for date_created
ALTER TABLE [dbo].[member_subscription] ADD CONSTRAINT [DF_member_subscription_datecreated] DEFAULT (getdate()) FOR [date_created]
GO
I inherited a SQL Server database that has a table with a primary key named RecordID. The table definition and the foreign key defined like this:
CREATE TABLE [dbo].[MyTable](
[RecordId] [int] IDENTITY(1,1) NOT NULL,
[FileName] [nvarchar](255) NOT NULL,
[Record] [nvarchar](255) NOT NULL,
[ErrorDescription] [nvarchar](255) NULL,
[ProcessDate] [datetime] NOT NULL,
CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED
(
[RecordId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[MyTable] WITH CHECK ADD CONSTRAINT [FK_MyTable_MyTable] FOREIGN KEY([RecordId])
REFERENCES [dbo].[MyTable] ([RecordId])
GO
ALTER TABLE [dbo].[MyTable] CHECK CONSTRAINT [FK_MyTable_MyTable]
GO
I could understand this if the foreign key referenced from a different field in the same table back to the primaray key field which would allow for a heirarchy, but in this case the two fields in the foreign key definition are exactly the same field. Is this just a mistake in the original definition of the table and foreign key? Or is there a real advantage somehow to this?
Thanks in advance for your time in replying.
Because the foreign key references itself, the check can never fail. That makes it, as a constraint, a no-op, so it is in every sense of the word, extraneous. Someone clearly made a mistake in creating the constraint.
I thought I might be missing something, so a quick check turned up with this: http://www.dotnetnuke.com/Resources/Forums/forumid/-1/postid/342163/scope/posts.aspx which reinforces my suspicion (user error). My most educated conclusion is that someone at some stage thought of creating a self-referencing (other column) table constraint, but in a wicked twist of confusion created this abomination.
I am trying to set a foreign key relationship between an Order_Items table and Parts table. I want to link the parts to products in the Order_Items table via foreign key. I have no issues doing this with other tables.
Here is how the Order_Items table is defined:
CREATE TABLE [dbo].[Order_Items](
[order_id] [uniqueidentifier] NOT NULL,
[product_number] [varchar](50) NOT NULL,
[quantity_ordered] [int] NOT NULL,
[product_tested] [bit] NULL,
CONSTRAINT [PK_Order_Items] PRIMARY KEY CLUSTERED
(
[order_id] ASC,
[product_number] 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].[Order_Items] WITH CHECK ADD CONSTRAINT [FK_Order_Items_Orders] FOREIGN KEY([order_id])
REFERENCES [dbo].[Orders] ([order_id])
GO
ALTER TABLE [dbo].[Order_Items] CHECK CONSTRAINT [FK_Order_Items_Orders]
and Parts table:
CREATE TABLE [dbo].[Parts](
[part_number] [varchar](50) NOT NULL,
[product_number] [varchar](50) NOT NULL,
[part_description] [varchar](max) NULL,
[part_tested] [bit] NULL,
CONSTRAINT [PK_Parts_1] PRIMARY KEY CLUSTERED
(
[part_number] ASC,
[product_number] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
I have tried setting the unique constraint on both product_number columns, but I still get the error message in SQL Server 2005 Management Studio Express as:
"The columns in table 'Order_Items' do not match an existing primary key or UNIQUE constraint"
Question: if [product_number] in your Parts table can be made unique by a unique constraint - why isn't it the primary key by itself??
My gut feeling: [product_number] in Parts isn't really unique - only the combination of (part_number, product_number), which is the primary key, really is unique.
If you can create a UNIQUE INDEX on the product_number column alone, you should be able to create the FK constraint - try this:
CREATE UNIQUE INDEX UIX01_Parts ON dbo.Parts(product_number)
ALTER TABLE dbo.Order_Items
ADD CONSTRAINT FK_OrderITems_Parts
FOREIGN KEY(product_number) REFERENCES dbo.Parts(product_number)
Does it work? If not - what error to you get, and where??
If that doesn't work, and only (part_number, product_number) is truly unique, then you need to reference both columns in your foreign key constraint:
ALTER TABLE dbo.Order_Items
ADD CONSTRAINT FK_OrderItems_Parts
FOREIGN KEY(part_number, product_number)
REFERENCES dbo.Parts(part_number, product_number)
and of course, this also means you need to have both those columns in your Order_Items table in order to be able to make the foreign key constraint work.
Just as a side note: having a compound primary key of two VARCHAR(50) columns and making that a clustered index on your Parts table is anything but optimal. If ever possible, try to make one or both of those "numbers" really a numeric type - e.g. an INT column. Or if that is not possible, think about having a surrogate PartID column (INT, IDENTITY) on your Parts table - that would make the FK constraint easier, too!
In order for this relationship to work, the Parts table cannot have composite key. In other words, you need to use product_number as the primary key since it is the column that they both have in common. You currently have part_number and product_number as your primary key.
Once you make that change, this statement will work:
ALTER TABLE [dbo].[Order_Items] WITH CHECK
ADD CONSTRAINT [FK_Order_Items_Parts] FOREIGN KEY([product_number])
REFERENCES [dbo].[Parts] ([product_number])
I ended up restructuring my entire database to get this to work and streamlined the table connections.