如何在从另一个表中提取数据时创建具有约束的表

Posted

技术标签:

【中文标题】如何在从另一个表中提取数据时创建具有约束的表【英文标题】:How do I create a table with constraints while pulling data from another table 【发布时间】:2018-11-07 04:23:57 【问题描述】:

我正在尝试创建一个 writers 表,其中包含作者 ID、姓氏、名字以及每位作者所写书籍的 ISBN 和标题。虽然使用与 author 和 books 表相同的数据类型,但不从这些表中复制数据。并包括作者 ID 作为主键,标题不为空,ISBN 作为外键引用图书表中的 ISBN。但是我收到“违反唯一约束 (WT_PK)”错误:

CREATE TABLE writers
  (authorid VARCHAR2(4),
    lname VARCHAR2(10),
    fname VARCHAR2(10),
    isbn VARCHAR2(10),
    title VARCHAR2(30) CONSTRAINT title_nn NOT NULL,
    CONSTRAINT wt_pk PRIMARY KEY(authorid),
    CONSTRAINT wt_fk FOREIGN KEY(isbn) REFERENCES books(isbn));

INSERT INTO writers
SELECT authorid, fname, lname, isbn, title 
FROM author 
   JOIN bookauthor USING(authorid) 
   JOIN books USING(isbn);

【问题讨论】:

你的表结构没有意义,除非你想要求作者只写一本书。 我添加了我试图从我的查询中得到的内容。如果我将约束放在列级别而不是表级别会有所不同吗? 。 .这没什么区别。您需要三张表,一张用于作者,一张用于书籍,一张用于书籍作者。 【参考方案1】:

您似乎需要为您的 WRITERS 表使用复合键。例子 (使用 Oracle 12c 和 11g 测试,dbfiddle here):

-- 4 authors
create table author ( authorid primary key, fname, lname )
as
select 1, 'fname_1', 'lname_1' from dual union all
select 2, 'fname_2', 'lname_2' from dual union all
select 3, 'fname_3', 'lname_3' from dual union all
select 4, 'fname_4', 'lname_4' from dual ;

-- 7 books
create table books ( isbn primary key, title )
as
select '978-1449324451', 'title_1' from dual union all
select '978-1449324452', 'title_2' from dual union all
select '978-1449324453', 'title_3' from dual union all
select '978-1449324454', 'title_1_4' from dual union all 
select '978-1449324455', 'title_2_4' from dual union all
select '978-1449324456', 'title_3_4' from dual union all
select '978-1449324457', 'title_4_4' from dual ;

-- suppose that 4 books are written by one and the same author
create table bookauthor( authorid, isbn )
as
select A.authorid, B.isbn
from author A 
  join books B on A.authorid = substr( B.title, length( B.title ), 1 ) ;

向 BOOKAUTHOR 表添加一些约束,并检查其内容:

-- authorid, isbn
alter table bookauthor 
add (
  constraint ba_fk1 foreign key( authorid ) references author( authorid )
, constraint ba_fk2 foreign key( isbn ) references books( isbn )
, constraint ba_pk primary key ( authorid, isbn )
) ;


SQL> select * from bookauthor;
  AUTHORID ISBN          
---------- --------------
         1 978-1449324451
         2 978-1449324452
         3 978-1449324453
         4 978-1449324454
         4 978-1449324455
         4 978-1449324456
         4 978-1449324457

“原始”DDL 代码(稍作修改)-> INSERT 失败

create table writers (
  authorid varchar2( 4 )
, lname varchar2( 10 )
, fname varchar2( 10 )
, isbn char( 14 )
, title varchar2( 30 ) constraint title_nn not null
, constraint wt_pk primary key ( authorid )
, constraint wt_fk foreign key( isbn ) references books( isbn )
);

INSERT INTO writers
SELECT authorid, fname, lname, isbn, title 
FROM author 
   JOIN bookauthor USING(authorid) 
   JOIN books USING(isbn);
-- ORA-00001: unique constraint (...WT_PK) violated 
-- author 4 with 4 books!

建议的 DDL 代码(和测试):

create table writers2 (
  authorid varchar2( 4 )
, lname varchar2( 10 )
, fname varchar2( 10 )
, isbn char( 14 )
, title varchar2( 30 ) constraint title_nn2 not null
, constraint wt_pk2 primary key ( authorid, isbn )
, constraint wt_fk2 foreign key( isbn ) references books( isbn )
);

INSERT INTO writers2
SELECT authorid, fname, lname, isbn, title 
FROM author 
   JOIN bookauthor USING(authorid) 
   JOIN books USING(isbn);
-- 7 rows inserted.

从 WRITERS2 中选择:

SQL> select * from writers2 ;

AUTH LNAME      FNAME      ISBN           TITLE                         
---- ---------- ---------- -------------- ------------------------------
1    fname_1    lname_1    978-1449324451 title_1                       
2    fname_2    lname_2    978-1449324452 title_2                       
3    fname_3    lname_3    978-1449324453 title_3                       
4    fname_4    lname_4    978-1449324454 title_1_4                     
4    fname_4    lname_4    978-1449324455 title_2_4                     
4    fname_4    lname_4    978-1449324456 title_3_4                     
4    fname_4    lname_4    978-1449324457 title_4_4 

但不确定为什么需要 WRITERS 表 - 因为您可以通过运行查询来生成其数据。

【讨论】:

【参考方案2】:

不妨试试这个:

   CREATE TABLE writers(
        authorid VARCHAR2(4),
        lname VARCHAR2(10),
        fname VARCHAR2(10),
        isbn VARCHAR2(10),
        title VARCHAR2(30) NOT NULL,
        CONSTRAINT wt_pk FOREIGN KEY(authorid) REFERENCES author(authorid),
        CONSTRAINT wt_fk FOREIGN KEY(isbn) REFERENCES books(isbn),
        UNIQUE KEY unique_authorid(authorid)
    );

只要确保这一行引用您的作者表主键(现在它是 authorid)

CONSTRAINT wt_pk FOREIGN KEY(authorid) REFERENCES author(authorid),

如果不需要,也删除唯一索引。 在您的示例中,您可能不需要它,因为一位作者可以拥有多个书名。你应该澄清你想要完成的事情。

【讨论】:

这仍然会导致authorid上的唯一键被违反的错误。

以上是关于如何在从另一个表中提取数据时创建具有约束的表的主要内容,如果未能解决你的问题,请参考以下文章

如何根据日期时间约束从另一个数据框中提取行?

如何从基于 sqlite 的日期约束中提取数据

从另一个访问一个数据库

详解如何定义SQL Server外关键字约束

如何从另一个表中获取数据并插入到 EF Core 中所需的表中

如何在从 Excel 导入的表中的 Access 中分配外键