如何在SQL Server中创build外键?

我从来没有为SQL Server“手工编码”对象创build代码,SQL Server和Postgres之间的外键删除看起来是不同的。 这是我的SQL到目前为止:

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 ); 

当我运行查询时,我得到这个错误:

消息8139,级别16,状态0,行9外键中引用列的数量不同于引用列的数量,表'question_bank'。

你能发现错误吗?

 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) ); 

如果你只是想创build约束,你可以使用ALTER TABLE

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

我不会推荐Sara Chipps提到的用于内联创build的语法,只是因为我宁愿命名我自己的约束。

您还可以使用以下命令来命名外键约束:

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

我喜欢AlexCuse的答案,但是当你添加一个外键约束的时候,你应该注意的是你想要如何更新被引用的表的一行中被引用的列来处理,特别是如何删除引用的行中的行表待治疗。

如果这样创build一个约束:

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

如果在引用表中存在对应的行,那么在被引用的表中更新或删除将会报错并报错。

这可能是你想要的行为,但根据我的经验,更常见的不是。

如果你反而像这样创build它:

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

..然后在父表中更新和删除将导致更新和删除引用表中的相应行。

(我并不是说这个默认值应该改变,这个默认的错误是谨慎的,这很好,我只是说这是一个创buildconstaints的人应该经常注意的东西。)

顺便说一下,创build表格时可以这样做:

 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 ) 
 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 ); 

– 那也行。 也许更直观的构造?

在任何表上创build一个外键

 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) 

和你一样,我通常不用手工创build外键,但是如果由于某种原因我需要这个脚本来做,所以我通常使用ms sql server management studio创build它,然后在保存和修改之前,我selectTable Designer | 生成更改脚本

Necromancing。
其实,正确做这件事有点棘手。

你首先需要检查你想设置你的外键引用的列是否存在主键。

在这个例子中,表T_ZO_SYS_Language_Forms上的外键被创build,引用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 

这个脚本是关于用外键创build表的,我添加了参照完整性约束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 ); 

如果要使用查询将两个表的列创build为关系,请尝试以下操作:

 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)