Sql 确保另一个表中存在两列的组合
如何确保另一个表中存在的两列的组合Sql 确保另一个表中存在两列的组合,sql,Sql,如何确保另一个表中存在的两列的组合 CREATE TABLE a ( aid INTEGER PRIMARY KEY ); CREATE TABLE b ( aid INTEGER REFERENCES a(aid), bid INTEGER, PRIMARY KEY (aid, bid) ); CREATE TABLE c ( aid INTEGER
CREATE TABLE a (
aid INTEGER PRIMARY KEY
);
CREATE TABLE b (
aid INTEGER REFERENCES a(aid),
bid INTEGER,
PRIMARY KEY (aid, bid)
);
CREATE TABLE c (
aid INTEGER REFERENCES a(aid),
cid INTEGER,
PRIMARY KEY (aid, cid)
);
-- combination of (aid, bid) must come from b
-- combination of (aid, cid) must come from c
CREATE TABLE d (
aid INTEGER REFERENCES a(aid),
bid INTEGER REFERENCES b(bid),
cid INTEGER REFERENCES c(bid),
PRIMARY KEY (aid, bid)
);
INSERT INTO a values(1);
INSERT INTO a values(2);
INSERT INTO b values(1, 1);
INSERT INTO b values(2, 2);
INSERT INTO c values(1, 1);
INSERT INTO c values(2, 2);
INSERT INTO d values(1, 2, 2);
显然,上述“创建表d”编码未能确保
- (援助、投标)的组合必须来自b
- (aid、cid)的组合必须来自c
谢谢。您不能内联定义多列外键约束。自己定义它们
CREATE TABLE d
(aid integer,
bid integer,
cid integer,
PRIMARY KEY (aid,
bid),
FOREIGN KEY (aid,
bid) REFERENCES b (aid,
bid),
FOREIGN KEY (aid,
cid) REFERENCES c (aid,
cid));
您没有指定正在使用的RDBMS。在SQL Server中,可以使用多个列创建外键。键应指向唯一键或主键中的列,并且表
B
和C
中确实有所需的主键
表A
、B
和C
的定义可以保留问题中的定义
表D
的定义在SQL Server语法中如下所示。这里使用单独的altertable
语句创建外键约束。不同的DBMS可能使用不同的语法
CREATE TABLE [dbo].[d](
[aid] [int] NULL,
[bid] [int] NULL,
[cid] [int] NULL
)
GO
ALTER TABLE [dbo].[d] WITH CHECK ADD CONSTRAINT [FK_d_b] FOREIGN KEY([aid], [bid])
REFERENCES [dbo].[b] ([aid], [bid])
GO
ALTER TABLE [dbo].[d] CHECK CONSTRAINT [FK_d_b]
GO
ALTER TABLE [dbo].[d] WITH CHECK ADD CONSTRAINT [FK_d_c] FOREIGN KEY([aid], [cid])
REFERENCES [dbo].[c] ([aid], [cid])
GO
ALTER TABLE [dbo].[d] CHECK CONSTRAINT [FK_d_c]
GO
它在我的测试中正常工作:
INSERT INTO a values(1);
INSERT INTO a values(2);
INSERT INTO b values(1, 1);
INSERT INTO b values(2, 2);
INSERT INTO c values(1, 1);
INSERT INTO c values(2, 2);
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
(1 row affected)
现在,让我们尝试插入到D
:
INSERT INTO d values(1, 2, 2);
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_d_b".
The conflict occurred in database "TestDB", table "dbo.b".
The statement has been terminated.
这些插入按预期进行:
INSERT INTO d values(1, 1, 1);
INSERT INTO d values(2, 2, 2);
(1 row affected)
(1 row affected)
INSERT INTO d2 values(1, 1, 1);
INSERT INTO d2 values(2, 2, 2);
(1 row affected)
(1 row affected)
也可以使用以下语法:
CREATE TABLE d2 (
aid INTEGER,
bid INTEGER,
cid INTEGER,
FOREIGN KEY (aid,bid) REFERENCES b (aid,bid),
FOREIGN KEY (aid,cid) REFERENCES c (aid,cid)
);
在这种情况下,外键将获得一些自动生成的名称,但它们的工作原理相同:
INSERT INTO d2 values(1, 2, 2);
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__d2__351DDF8C".
The conflict occurred in database "TestDB", table "dbo.b".
The statement has been terminated.
INSERT INTO d2 values(1, 1, 2);
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__d2__361203C5".
The conflict occurred in database "TestDB", table "dbo.c".
The statement has been terminated.
正如预期的那样,这些插入工作正常:
INSERT INTO d values(1, 1, 1);
INSERT INTO d values(2, 2, 2);
(1 row affected)
(1 row affected)
INSERT INTO d2 values(1, 1, 1);
INSERT INTO d2 values(2, 2, 2);
(1 row affected)
(1 row affected)
或者,您可以使用此语法为约束指定一些有意义的名称:
CREATE TABLE d3 (
aid INTEGER,
bid INTEGER,
cid INTEGER,
CONSTRAINT FK_d3_b FOREIGN KEY (aid,bid) REFERENCES b (aid,bid),
CONSTRAINT FK_d3_c FOREIGN KEY (aid,cid) REFERENCES c (aid,cid)
);
除了Stick bit和Vladimir Baranov关于使用外键和引用的回答之外,对于sqlite3用户: 这意味着,用户必须首先打开数据库,然后运行命令“PRAGMA foreign_keys=ON;”
如果“您正在使用的SQLite版本不支持外键(可能是因为它早于3.6.19,或者是因为它是使用SQLite_OMIT_foreign_KEY或SQLite_OMIT_TRIGGER defined编译的)”,则pragma将不起作用。感谢您的快速响应。但是,这不会停止“插入d值(1,2,2);”行以创建记录:(1,2)(aid,bid)不在b中,(1,2)(aid,cid)也不在c中。您对
d
的定义应该失败,因为引用的不是主键或唯一键。这是正确的。这是我想解决的问题的一部分。谢谢你的详细解释。我使用的RDBMS是sqlite3。经过一番努力,我终于发现在sqlite3中“外键约束在默认情况下是禁用的(为了向后兼容)”。