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中“外键约束在默认情况下是禁用的(为了向后兼容)”。