How do I create a foreign key in SQL Server?

SqlSql ServerTsql

Sql Problem Overview


I have never "hand-coded" object creation code for SQL Server and foreign key decleration is seemingly different between SQL Server and Postgres. Here is my sql so far:

drop table exams;
drop table question_bank;
drop table anwser_bank;

create table exams
(
	exam_id uniqueidentifier primary key,
    exam_name varchar(50),
);
create table question_bank
(
	question_id uniqueidentifier primary key,
	question_exam_id uniqueidentifier not null,
    question_text varchar(1024) not null,
    question_point_value decimal,
    constraint question_exam_id foreign key references exams(exam_id)
);
create table anwser_bank
(
	anwser_id			uniqueidentifier primary key,
	anwser_question_id	uniqueidentifier,
	anwser_text			varchar(1024),
	anwser_is_correct	bit
);

When I run the query I get this error:

> Msg 8139, Level 16, State 0, Line 9 > Number of referencing columns in > foreign key differs from number of > referenced columns, table > 'question_bank'.

Can you spot the error?

Sql Solutions


Solution 1 - Sql

And if you just want to create the constraint on its own, you can use ALTER TABLE

alter table MyTable
add constraint MyTable_MyColumn_FK FOREIGN KEY ( MyColumn ) references MyOtherTable(PKColumn)

I wouldn't recommend the syntax mentioned by Sara Chipps for inline creation, just because I would rather name my own constraints.

Solution 2 - Sql

create table question_bank
(
    question_id uniqueidentifier primary key,
    question_exam_id uniqueidentifier not null,
    question_text varchar(1024) not null,
    question_point_value decimal,
    constraint fk_questionbank_exams foreign key (question_exam_id) references exams (exam_id)
);

Solution 3 - Sql

You can also name your foreign key constraint by using:

CONSTRAINT your_name_here FOREIGN KEY (question_exam_id) REFERENCES EXAMS (exam_id)

Solution 4 - Sql

I like AlexCuse's answer, but something you should pay attention to whenever you add a foreign key constraint is how you want updates to the referenced column in a row of the referenced table to be treated, and especially how you want deletes of rows in the referenced table to be treated.

If a constraint is created like this:

alter table MyTable
add constraint MyTable_MyColumn_FK FOREIGN KEY ( MyColumn ) 
references MyOtherTable(PKColumn)

.. then updates or deletes in the referenced table will blow up with an error if there is a corresponding row in the referencing table.

That might be the behaviour you want, but in my experience, it much more commonly isn't.

If you instead create it like this:

alter table MyTable
add constraint MyTable_MyColumn_FK FOREIGN KEY ( MyColumn ) 
references MyOtherTable(PKColumn)
on update cascade 
on delete cascade

..then updates and deletes in the parent table will result in updates and deletes of the corresponding rows in the referencing table.

(I'm not suggesting that the default should be changed, the default errs on the side of caution, which is good. I'm just saying it's something that a person who is creating constaints should always pay attention to.)

This can be done, by the way, when creating a table, like this:

create table ProductCategories (
  Id           int identity primary key,
  ProductId    int references Products(Id)
               on update cascade on delete cascade
  CategoryId   int references Categories(Id) 
               on update cascade on delete cascade
)

Solution 5 - Sql

create table question_bank
(
    question_id uniqueidentifier primary key,
    question_exam_id uniqueidentifier not null constraint fk_exam_id foreign key references exams(exam_id),
    question_text varchar(1024) not null,
    question_point_value decimal
);

--That will work too. Pehaps a bit more intuitive construct?

Solution 6 - Sql

To Create a foreign key on any table

ALTER TABLE [SCHEMA].[TABLENAME] ADD FOREIGN KEY (COLUMNNAME) REFERENCES [TABLENAME](COLUMNNAME)
EXAMPLE
ALTER TABLE [dbo].[UserMaster] ADD FOREIGN KEY (City_Id) REFERENCES [dbo].[CityMaster](City_Id)

Solution 7 - Sql

If you want to create two table's columns into a relationship by using a query try the following:

Alter table Foreign_Key_Table_name add constraint 
Foreign_Key_Table_name_Columnname_FK
Foreign Key (Column_name) references 
Another_Table_name(Another_Table_Column_name)

Solution 8 - Sql

Like you, I don't usually create foreign keys by hand, but if for some reason I need the script to do so I usually create it using ms sql server management studio and before saving then changes, I select Table Designer | Generate Change Script

Solution 9 - Sql

This script is about creating tables with foreign key and I added referential integrity constraint sql-server.

create table exams
(  
    exam_id int primary key,
    exam_name varchar(50),
);

create table question_bank 
(
    question_id int primary key,
    question_exam_id int not null,
    question_text varchar(1024) not null,
    question_point_value decimal,
    constraint question_exam_id_fk
       foreign key references exams(exam_id)
               ON DELETE CASCADE
);

Solution 10 - Sql

Necromancing.
Actually, doing this correctly is a little bit trickier.

You first need to check if the primary-key exists for the column you want to set your foreign key to reference to.

In this example, a foreign key on table T_ZO_SYS_Language_Forms is created, referencing dbo.T_SYS_Language_Forms.LANG_UID

-- First, chech if the table exists...
IF 0 < (
	SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES 
	WHERE TABLE_TYPE = 'BASE TABLE'
	AND TABLE_SCHEMA = 'dbo'
	AND TABLE_NAME = 'T_SYS_Language_Forms'
)
BEGIN
	-- Check for NULL values in the primary-key column
	IF 0 = (SELECT COUNT(*) FROM T_SYS_Language_Forms WHERE LANG_UID IS NULL)
	BEGIN
		ALTER TABLE T_SYS_Language_Forms ALTER COLUMN LANG_UID uniqueidentifier NOT NULL 
		
		-- No, don't drop, FK references might already exist...
		-- Drop PK if exists 
		-- ALTER TABLE T_SYS_Language_Forms DROP CONSTRAINT pk_constraint_name 
		--DECLARE @pkDropCommand nvarchar(1000) 
		--SET @pkDropCommand = N'ALTER TABLE T_SYS_Language_Forms DROP CONSTRAINT ' + QUOTENAME((SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
		--WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' 
		--AND TABLE_SCHEMA = 'dbo' 
		--AND TABLE_NAME = 'T_SYS_Language_Forms' 
		----AND CONSTRAINT_NAME = 'PK_T_SYS_Language_Forms' 
		--))
		---- PRINT @pkDropCommand 
		--EXECUTE(@pkDropCommand) 
		
		-- Instead do
		-- EXEC sp_rename 'dbo.T_SYS_Language_Forms.PK_T_SYS_Language_Forms1234565', 'PK_T_SYS_Language_Forms';
		
		
		-- Check if they keys are unique (it is very possible they might not be) 
		IF 1 >= (SELECT TOP 1 COUNT(*) AS cnt FROM T_SYS_Language_Forms GROUP BY LANG_UID ORDER BY cnt DESC)
		BEGIN
			
			-- If no Primary key for this table
			IF 0 =  
			(
				SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
				WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' 
				AND TABLE_SCHEMA = 'dbo' 
				AND TABLE_NAME = 'T_SYS_Language_Forms' 
				-- AND CONSTRAINT_NAME = 'PK_T_SYS_Language_Forms' 
			)
				ALTER TABLE T_SYS_Language_Forms ADD CONSTRAINT PK_T_SYS_Language_Forms PRIMARY KEY CLUSTERED (LANG_UID ASC)
			;
			
			-- Adding foreign key
			IF 0 = (SELECT COUNT(*) FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_T_ZO_SYS_Language_Forms_T_SYS_Language_Forms') 
				ALTER TABLE T_ZO_SYS_Language_Forms WITH NOCHECK ADD CONSTRAINT FK_T_ZO_SYS_Language_Forms_T_SYS_Language_Forms FOREIGN KEY(ZOLANG_LANG_UID) REFERENCES T_SYS_Language_Forms(LANG_UID); 
		END -- End uniqueness check
		ELSE
			PRINT 'FSCK, this column has duplicate keys, and can thus not be changed to primary key...' 
	END -- End NULL check
	ELSE
		PRINT 'FSCK, need to figure out how to update NULL value(s)...' 
END 

Solution 11 - Sql

I always use this syntax to create the foreign key constraint between 2 tables

Alter Table ForeignKeyTable
Add constraint `ForeignKeyTable_ForeignKeyColumn_FK`
`Foreign key (ForeignKeyColumn)` references `PrimaryKeyTable (PrimaryKeyColumn)`

i.e.

Alter Table tblEmployee
Add constraint tblEmployee_DepartmentID_FK
foreign key (DepartmentID) references tblDepartment (ID)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmmattaxView Question on Stackoverflow
Solution 1 - SqlAlexCuseView Answer on Stackoverflow
Solution 2 - SqlJohn BokerView Answer on Stackoverflow
Solution 3 - SqlSara ChippsView Answer on Stackoverflow
Solution 4 - SqlShavaisView Answer on Stackoverflow
Solution 5 - SqlBijimonView Answer on Stackoverflow
Solution 6 - SqlAbhishek JaiswalView Answer on Stackoverflow
Solution 7 - SqlMd Ashikul IslamView Answer on Stackoverflow
Solution 8 - SqlVitor SilvaView Answer on Stackoverflow
Solution 9 - Sqlelkhayari abderrazzakView Answer on Stackoverflow
Solution 10 - SqlStefan SteigerView Answer on Stackoverflow
Solution 11 - SqlAamir ShaikhView Answer on Stackoverflow