SQL中一个联合主键(a,b)中的一个字段a可以作为外键吗?
15 个解决方案
#1
• 外键约束并不仅仅可以与另一表的主键约束相链接,它还可以定义为引用另一个表中 UNIQUE 约束的列。
• 如果在 FOREIGN KEY 约束的列中输入非 NULL 值,则此值必须在被引用列中存在;否则,将返回违反外键约束的错误信息。 若要确保验证了组合外键约束的所有值,请对所有参与列指定 NOT NULL。
• FOREIGN KEY 约束仅能引用位于同一服务器上的同一数据库中的表。 跨数据库的引用完整性必须通过触发器实现。 有关详细信息,请参阅 CREATE TRIGGER (Transact-SQL)。
• FOREIGN KEY 约束可引用同一表中的其他列。 此行为称为自引用。
• 在列级指定的 FOREIGN KEY 约束只能列出一个引用列。 此列的数据类型必须与定义约束的列的数据类型相同。
• 在表级指定的 FOREIGN KEY 约束所具有的引用列数目必须与约束列列表中的列数相同。 每个引用列的数据类型也必须与列表中相应列的数据类型相同。
• 对于表可包含的引用其他表的 FOREIGN KEY 约束的数目或其他表所拥有的引用特定表的 FOREIGN KEY 约束的数目,数据库引擎都没有预定义的限制。 尽管如此,可使用的 FOREIGN KEY 约束的实际数目还是受硬件配置以及数据库和应用程序设计的限制。 建议表中包含的 FOREIGN KEY 约束不要超过 253 个,并且引用该表的 FOREIGN KEY 约束也不要超过 253 个。
• 对于临时表不强制 FOREIGN KEY 约束。
• 如果在 CLR 用户定义类型的列上定义外键,则该类型的实现必须支持二进制排序。 有关详细信息,请参阅 CLR 用户定义类型。
• 仅当 FOREIGN KEY 约束引用的主键也定义为类型 varchar(max) 时,才能在此约束中使用类型为 varchar(max) 的列。
来自 < http://msdn.microsoft.com/zh-cn/library/ms189049.aspx>
• 如果在 FOREIGN KEY 约束的列中输入非 NULL 值,则此值必须在被引用列中存在;否则,将返回违反外键约束的错误信息。 若要确保验证了组合外键约束的所有值,请对所有参与列指定 NOT NULL。
• FOREIGN KEY 约束仅能引用位于同一服务器上的同一数据库中的表。 跨数据库的引用完整性必须通过触发器实现。 有关详细信息,请参阅 CREATE TRIGGER (Transact-SQL)。
• FOREIGN KEY 约束可引用同一表中的其他列。 此行为称为自引用。
• 在列级指定的 FOREIGN KEY 约束只能列出一个引用列。 此列的数据类型必须与定义约束的列的数据类型相同。
• 在表级指定的 FOREIGN KEY 约束所具有的引用列数目必须与约束列列表中的列数相同。 每个引用列的数据类型也必须与列表中相应列的数据类型相同。
• 对于表可包含的引用其他表的 FOREIGN KEY 约束的数目或其他表所拥有的引用特定表的 FOREIGN KEY 约束的数目,数据库引擎都没有预定义的限制。 尽管如此,可使用的 FOREIGN KEY 约束的实际数目还是受硬件配置以及数据库和应用程序设计的限制。 建议表中包含的 FOREIGN KEY 约束不要超过 253 个,并且引用该表的 FOREIGN KEY 约束也不要超过 253 个。
• 对于临时表不强制 FOREIGN KEY 约束。
• 如果在 CLR 用户定义类型的列上定义外键,则该类型的实现必须支持二进制排序。 有关详细信息,请参阅 CLR 用户定义类型。
• 仅当 FOREIGN KEY 约束引用的主键也定义为类型 varchar(max) 时,才能在此约束中使用类型为 varchar(max) 的列。
来自 < http://msdn.microsoft.com/zh-cn/library/ms189049.aspx>
#2
--行不行试试不就知道了?
drop table t_1
create table t_1
(
col1 varchar(10) not null,
col2 varchar(10)not null
)
drop table t_2
create table t_2
(
col1 varchar(10),
col2 varchar(10)
)
alter table t_1
add constraint pk_id primary key(col1,col2)
命令已成功完成。
alter table t_2
add constraint fk_col1 foreign key(col1) references t_1(col1)
消息 1776,级别 16,状态 0,第 1 行
在被引用表 't_1' 中没有与外键 'fk_col1' 中的引用列列表匹配的主键或候选键。
消息 1750,级别 16,状态 0,第 1 行
无法创建约束。请参阅前面的错误消息。
alter table t_1
add constraint UQ_COL1
unique(col1)
命令已成功完成。
alter table t_2
add constraint fk_col1 foreign key(col1) references t_1(col1)
命令已成功完成。
#3
不可以,建立外键的一条规则:
外键列引用的
列必须是
唯一的,举2个例子:
例子1:
A(a) 如果 a字段是A表主键 ----〉表明a在A表中 是唯一的------〉可以被引用
B (b) 此时b字段基于A表的a字段建立外键是 合法的
列子2:
A(a1,a2) 如果 a1和a2两个字段是A表主键 ----〉a1或者a2字段在A表中 不是唯一的-----〉不可以被单独引用 (如果要引用,必须是a1和a2两个列同时被引用)
B (b) 此时b字段基于A表的a1字段建立外键是 非法的
例子1:
A(a) 如果 a字段是A表主键 ----〉表明a在A表中 是唯一的------〉可以被引用
B (b) 此时b字段基于A表的a字段建立外键是 合法的
列子2:
A(a1,a2) 如果 a1和a2两个字段是A表主键 ----〉a1或者a2字段在A表中 不是唯一的-----〉不可以被单独引用 (如果要引用,必须是a1和a2两个列同时被引用)
B (b) 此时b字段基于A表的a1字段建立外键是 非法的
#4
哦!首先感谢各位及时的答复,可能是我没有表述清楚,应该是:
建表t1(a,b,c...) 其中(a,b)是联合主键,建表t2(a,b,c...)其中a是主键,现在要设置t1.a为参考t2.a的外键,
即:ALTER TABLE [dbo].[t1] ADD CONSTRAINT [FK_12] FOREIGN KEY([a])
REFERENCES [dbo].[t2] ([a]);这个为啥不行?
建表t1(a,b,c...) 其中(a,b)是联合主键,建表t2(a,b,c...)其中a是主键,现在要设置t1.a为参考t2.a的外键,
即:ALTER TABLE [dbo].[t1] ADD CONSTRAINT [FK_12] FOREIGN KEY([a])
REFERENCES [dbo].[t2] ([a]);这个为啥不行?
#5
外键引用要求被引用的表上有主键,其实是为了唯一性,而组合主键的话,单纯一个列无法保证唯一(最起码sqlserver认为)
#6
,我这表述能力太差了 或者我始终把概念混淆了,现在是被引用的那个字段已经是它的那个表的主键了,引用的这个是一个表中联合主键的一个字段 ,但是会报错 不知道为什么?
#7
这个可以,t2.a已经是主键了,保证其唯一性,没有违反创建外键的规则。你测试的情况如果有错,请贴出所有代码
#8
是不是这个意思:
表t1,有一个字段a,是主鍵。
表t2,有两个字段a、b,是联合主键。
现在是想要表t2的字段a设定成表t1字段a的外键。
我试过了,可以这样操作啊。
表t1,有一个字段a,是主鍵。
表t2,有两个字段a、b,是联合主键。
现在是想要表t2的字段a设定成表t1字段a的外键。
我试过了,可以这样操作啊。
#9
IF OBJECT_ID('ta') IS NOT NULL
DROP TABLE dbo.ta
GO
CREATE TABLE Ta
(
ID INT NOT NULL,
Val VARCHAR(32)
)
ALTER TABLE ta ADD PRIMARY KEY(ID)
GO
IF OBJECT_ID('tb') IS NOT NULL
DROP TABLE dbo.TB
GO
CREATE TABLE Tb
(
ID1 INT NOT NULL,
ID2 INT NOT NULL,
Val VARCHAR(32)
)
GO
ALTER TABLE TB ADD PRIMARY KEY(ID1,ID2)
ALTER TABLE TB ADD CONSTRAINT pk_id FOREIGN KEY (ID1) REFERENCES ta(ID)
GO
#10
问题已经解决,我把表给删了,重新建立一遍,建表的时候指定外键,就可以了,在最开始建完之后修改的时候会报错,以为是权限不够,就换了owner用户来试,可以了但是刷新表的键不会出现建的外键,抽风了,果断表删了重建,OK了!
#11
有可能是表中数据不对,导致不能建外键。
#12
虽然没有完美了解,但也算解决了,结贴喽。。。
#13
楼主,想问一下,你的使用的配置文件还是注解,能不能私聊下,我的测试通过了,但是数据库中添加不上数据
#14
我也遇到这个问题啊 真是日了狗了
Create table Zj_Class
(
Gx_No char(6) ,
Xq_No char (2) ,
Xy_No char(2),
Class_No char(10) unique ,
Class_Age int,
Class_Major char(20),
Class_Header char(20),
primary key(Gx_no,Xq_no,Xy_no,Class_NO),
Constraint Class_Xy foreign key(Gx_no,Xq_no,Xy_no) references Zj_XueYuan
)
--班级(学校编号,校区编号,学院编号,班级编号,年级,专业,班长)
Create table Zj_Stu
(
Class_No char(10) ,
Stu_No char(12) ,
Stu_Name char(20),
Stu_Sex char(4),
Stu_Age int,
Stu_Address char(20),
Stu_Tel char(12)
primary key(Class_no,Stu_no),
Constraint Stu_Class foreign key(Class_NO) references Zj_Class
)
--学生(班级编号,学号,姓名,性别,年龄,籍贯,电话)
Create table Zj_Class
(
Gx_No char(6) ,
Xq_No char (2) ,
Xy_No char(2),
Class_No char(10) unique ,
Class_Age int,
Class_Major char(20),
Class_Header char(20),
primary key(Gx_no,Xq_no,Xy_no,Class_NO),
Constraint Class_Xy foreign key(Gx_no,Xq_no,Xy_no) references Zj_XueYuan
)
--班级(学校编号,校区编号,学院编号,班级编号,年级,专业,班长)
Create table Zj_Stu
(
Class_No char(10) ,
Stu_No char(12) ,
Stu_Name char(20),
Stu_Sex char(4),
Stu_Age int,
Stu_Address char(20),
Stu_Tel char(12)
primary key(Class_no,Stu_no),
Constraint Stu_Class foreign key(Class_NO) references Zj_Class
)
--学生(班级编号,学号,姓名,性别,年龄,籍贯,电话)
#15
所以要怎么做才可以啊
#1
• 外键约束并不仅仅可以与另一表的主键约束相链接,它还可以定义为引用另一个表中 UNIQUE 约束的列。
• 如果在 FOREIGN KEY 约束的列中输入非 NULL 值,则此值必须在被引用列中存在;否则,将返回违反外键约束的错误信息。 若要确保验证了组合外键约束的所有值,请对所有参与列指定 NOT NULL。
• FOREIGN KEY 约束仅能引用位于同一服务器上的同一数据库中的表。 跨数据库的引用完整性必须通过触发器实现。 有关详细信息,请参阅 CREATE TRIGGER (Transact-SQL)。
• FOREIGN KEY 约束可引用同一表中的其他列。 此行为称为自引用。
• 在列级指定的 FOREIGN KEY 约束只能列出一个引用列。 此列的数据类型必须与定义约束的列的数据类型相同。
• 在表级指定的 FOREIGN KEY 约束所具有的引用列数目必须与约束列列表中的列数相同。 每个引用列的数据类型也必须与列表中相应列的数据类型相同。
• 对于表可包含的引用其他表的 FOREIGN KEY 约束的数目或其他表所拥有的引用特定表的 FOREIGN KEY 约束的数目,数据库引擎都没有预定义的限制。 尽管如此,可使用的 FOREIGN KEY 约束的实际数目还是受硬件配置以及数据库和应用程序设计的限制。 建议表中包含的 FOREIGN KEY 约束不要超过 253 个,并且引用该表的 FOREIGN KEY 约束也不要超过 253 个。
• 对于临时表不强制 FOREIGN KEY 约束。
• 如果在 CLR 用户定义类型的列上定义外键,则该类型的实现必须支持二进制排序。 有关详细信息,请参阅 CLR 用户定义类型。
• 仅当 FOREIGN KEY 约束引用的主键也定义为类型 varchar(max) 时,才能在此约束中使用类型为 varchar(max) 的列。
来自 < http://msdn.microsoft.com/zh-cn/library/ms189049.aspx>
• 如果在 FOREIGN KEY 约束的列中输入非 NULL 值,则此值必须在被引用列中存在;否则,将返回违反外键约束的错误信息。 若要确保验证了组合外键约束的所有值,请对所有参与列指定 NOT NULL。
• FOREIGN KEY 约束仅能引用位于同一服务器上的同一数据库中的表。 跨数据库的引用完整性必须通过触发器实现。 有关详细信息,请参阅 CREATE TRIGGER (Transact-SQL)。
• FOREIGN KEY 约束可引用同一表中的其他列。 此行为称为自引用。
• 在列级指定的 FOREIGN KEY 约束只能列出一个引用列。 此列的数据类型必须与定义约束的列的数据类型相同。
• 在表级指定的 FOREIGN KEY 约束所具有的引用列数目必须与约束列列表中的列数相同。 每个引用列的数据类型也必须与列表中相应列的数据类型相同。
• 对于表可包含的引用其他表的 FOREIGN KEY 约束的数目或其他表所拥有的引用特定表的 FOREIGN KEY 约束的数目,数据库引擎都没有预定义的限制。 尽管如此,可使用的 FOREIGN KEY 约束的实际数目还是受硬件配置以及数据库和应用程序设计的限制。 建议表中包含的 FOREIGN KEY 约束不要超过 253 个,并且引用该表的 FOREIGN KEY 约束也不要超过 253 个。
• 对于临时表不强制 FOREIGN KEY 约束。
• 如果在 CLR 用户定义类型的列上定义外键,则该类型的实现必须支持二进制排序。 有关详细信息,请参阅 CLR 用户定义类型。
• 仅当 FOREIGN KEY 约束引用的主键也定义为类型 varchar(max) 时,才能在此约束中使用类型为 varchar(max) 的列。
来自 < http://msdn.microsoft.com/zh-cn/library/ms189049.aspx>
#2
--行不行试试不就知道了?
drop table t_1
create table t_1
(
col1 varchar(10) not null,
col2 varchar(10)not null
)
drop table t_2
create table t_2
(
col1 varchar(10),
col2 varchar(10)
)
alter table t_1
add constraint pk_id primary key(col1,col2)
命令已成功完成。
alter table t_2
add constraint fk_col1 foreign key(col1) references t_1(col1)
消息 1776,级别 16,状态 0,第 1 行
在被引用表 't_1' 中没有与外键 'fk_col1' 中的引用列列表匹配的主键或候选键。
消息 1750,级别 16,状态 0,第 1 行
无法创建约束。请参阅前面的错误消息。
alter table t_1
add constraint UQ_COL1
unique(col1)
命令已成功完成。
alter table t_2
add constraint fk_col1 foreign key(col1) references t_1(col1)
命令已成功完成。
#3
不可以,建立外键的一条规则:
外键列引用的
列必须是
唯一的,举2个例子:
例子1:
A(a) 如果 a字段是A表主键 ----〉表明a在A表中 是唯一的------〉可以被引用
B (b) 此时b字段基于A表的a字段建立外键是 合法的
列子2:
A(a1,a2) 如果 a1和a2两个字段是A表主键 ----〉a1或者a2字段在A表中 不是唯一的-----〉不可以被单独引用 (如果要引用,必须是a1和a2两个列同时被引用)
B (b) 此时b字段基于A表的a1字段建立外键是 非法的
例子1:
A(a) 如果 a字段是A表主键 ----〉表明a在A表中 是唯一的------〉可以被引用
B (b) 此时b字段基于A表的a字段建立外键是 合法的
列子2:
A(a1,a2) 如果 a1和a2两个字段是A表主键 ----〉a1或者a2字段在A表中 不是唯一的-----〉不可以被单独引用 (如果要引用,必须是a1和a2两个列同时被引用)
B (b) 此时b字段基于A表的a1字段建立外键是 非法的
#4
哦!首先感谢各位及时的答复,可能是我没有表述清楚,应该是:
建表t1(a,b,c...) 其中(a,b)是联合主键,建表t2(a,b,c...)其中a是主键,现在要设置t1.a为参考t2.a的外键,
即:ALTER TABLE [dbo].[t1] ADD CONSTRAINT [FK_12] FOREIGN KEY([a])
REFERENCES [dbo].[t2] ([a]);这个为啥不行?
建表t1(a,b,c...) 其中(a,b)是联合主键,建表t2(a,b,c...)其中a是主键,现在要设置t1.a为参考t2.a的外键,
即:ALTER TABLE [dbo].[t1] ADD CONSTRAINT [FK_12] FOREIGN KEY([a])
REFERENCES [dbo].[t2] ([a]);这个为啥不行?
#5
外键引用要求被引用的表上有主键,其实是为了唯一性,而组合主键的话,单纯一个列无法保证唯一(最起码sqlserver认为)
#6
,我这表述能力太差了 或者我始终把概念混淆了,现在是被引用的那个字段已经是它的那个表的主键了,引用的这个是一个表中联合主键的一个字段 ,但是会报错 不知道为什么?
#7
这个可以,t2.a已经是主键了,保证其唯一性,没有违反创建外键的规则。你测试的情况如果有错,请贴出所有代码
#8
是不是这个意思:
表t1,有一个字段a,是主鍵。
表t2,有两个字段a、b,是联合主键。
现在是想要表t2的字段a设定成表t1字段a的外键。
我试过了,可以这样操作啊。
表t1,有一个字段a,是主鍵。
表t2,有两个字段a、b,是联合主键。
现在是想要表t2的字段a设定成表t1字段a的外键。
我试过了,可以这样操作啊。
#9
IF OBJECT_ID('ta') IS NOT NULL
DROP TABLE dbo.ta
GO
CREATE TABLE Ta
(
ID INT NOT NULL,
Val VARCHAR(32)
)
ALTER TABLE ta ADD PRIMARY KEY(ID)
GO
IF OBJECT_ID('tb') IS NOT NULL
DROP TABLE dbo.TB
GO
CREATE TABLE Tb
(
ID1 INT NOT NULL,
ID2 INT NOT NULL,
Val VARCHAR(32)
)
GO
ALTER TABLE TB ADD PRIMARY KEY(ID1,ID2)
ALTER TABLE TB ADD CONSTRAINT pk_id FOREIGN KEY (ID1) REFERENCES ta(ID)
GO
#10
问题已经解决,我把表给删了,重新建立一遍,建表的时候指定外键,就可以了,在最开始建完之后修改的时候会报错,以为是权限不够,就换了owner用户来试,可以了但是刷新表的键不会出现建的外键,抽风了,果断表删了重建,OK了!
#11
有可能是表中数据不对,导致不能建外键。
#12
虽然没有完美了解,但也算解决了,结贴喽。。。
#13
楼主,想问一下,你的使用的配置文件还是注解,能不能私聊下,我的测试通过了,但是数据库中添加不上数据
#14
我也遇到这个问题啊 真是日了狗了
Create table Zj_Class
(
Gx_No char(6) ,
Xq_No char (2) ,
Xy_No char(2),
Class_No char(10) unique ,
Class_Age int,
Class_Major char(20),
Class_Header char(20),
primary key(Gx_no,Xq_no,Xy_no,Class_NO),
Constraint Class_Xy foreign key(Gx_no,Xq_no,Xy_no) references Zj_XueYuan
)
--班级(学校编号,校区编号,学院编号,班级编号,年级,专业,班长)
Create table Zj_Stu
(
Class_No char(10) ,
Stu_No char(12) ,
Stu_Name char(20),
Stu_Sex char(4),
Stu_Age int,
Stu_Address char(20),
Stu_Tel char(12)
primary key(Class_no,Stu_no),
Constraint Stu_Class foreign key(Class_NO) references Zj_Class
)
--学生(班级编号,学号,姓名,性别,年龄,籍贯,电话)
Create table Zj_Class
(
Gx_No char(6) ,
Xq_No char (2) ,
Xy_No char(2),
Class_No char(10) unique ,
Class_Age int,
Class_Major char(20),
Class_Header char(20),
primary key(Gx_no,Xq_no,Xy_no,Class_NO),
Constraint Class_Xy foreign key(Gx_no,Xq_no,Xy_no) references Zj_XueYuan
)
--班级(学校编号,校区编号,学院编号,班级编号,年级,专业,班长)
Create table Zj_Stu
(
Class_No char(10) ,
Stu_No char(12) ,
Stu_Name char(20),
Stu_Sex char(4),
Stu_Age int,
Stu_Address char(20),
Stu_Tel char(12)
primary key(Class_no,Stu_no),
Constraint Stu_Class foreign key(Class_NO) references Zj_Class
)
--学生(班级编号,学号,姓名,性别,年龄,籍贯,电话)
#15
所以要怎么做才可以啊