【问题标题】:Sql (Oracle) : insert a duplicate keySql (Oracle) : 插入重复键
【发布时间】:2018-05-16 19:51:47
【问题描述】:

Harry 是巫师,他创建了一个名为“the Fellowship of the Ring”的团体。Harry 的巫师号是 77。

INSERT INTO group VALUES ('the fellowship of the ring','01');
INSERT INTO activity VALUES ('01','77','the fellowship of the ring’);

Gondor 也想加入群组和活动01。

从表中,我们知道“wizardno”是向导表的主键。

“groupname”是组表的主键。“acitvityno”是组表的UF键。

“acitvityno”是活动表的主键。

“groupname”是活动表的外键。 “wizardno”是活动表的UF键。在

将刚铎加入哈利的队伍。刚铎的巫师号是 99。

我用

insert into activity values (’01’,’99’,’the fellowship of the ring’);

得到错误: 原因:UPDATE 或 INSERT 语句试图插入重复键。 对于在 DBMS MAC 模式下配置的 Trusted Oracle,如果在不同级别存在重复条目,您可能会看到此消息。 *操作:要么删除唯一限制,要么不插入密钥。

但它必须保持唯一的限制。

drop table wizard;
drop table activity;
drop table group; 

CREATE TABLE wizard (
    wizardno          NUMBER(2) NOT NULL,
    wizardname        VARCHAR2(30) NOT NULL,
   );

ALTER TABLE wizard ADD CONSTRAINT wizard_pk PRIMARY KEY ( wizardno );
CREATE TABLE group (
    groupname        VARCHAR2(30) NOT NULL,
    activityno         NUMBER(2) NOT NULL
);

ALTER TABLE group ADD CONSTRAINT group_pk PRIMARY KEY ( groupname );


CREATE TABLE activity (
    activityno        NUMBER(2) NOT NULL,
    wizardno          CHAR(2) NOT NULL,
    groupname         VARCHAR2(30)
);   

ALTER TABLE activity 
   ADD CONSTRAINT activity_pk PRIMARY KEY ( activityno );

ALTER TABLE activity
    ADD CONSTRAINT activity_wizard_fk FOREIGN KEY ( wizardno )
        REFERENCES wizard ( wizardno );
ALTER TABLE  activity
    ADD CONSTRAINT activity_group_fk FOREIGN KEY ( groupname )
        REFERENCES group ( groupname );

【问题讨论】:

  • 提示:你知道“主键”是什么意思吗?
  • 约束唯一标识每条记录
  • @AAlex 在旁注中Why the fellowship of the ring 在组和活动表中都有定义?
  • 活动多,组参加其中一项活动。
  • @AAlex 作为最佳实践,请避免使用长描述作为连接表的键。

标签: sql oracle


【解决方案1】:
  • 不要使用保留字group 作为表名
  • 对字符串类型变量使用正确的单引号''
  • 您需要为查找表插入相应的值( 在这种情况下 wizard ),您引用它的完整性 表格。

  • 对于外键和主键关系,两个引用列在 两个表应该是相同的类型(您可以将wizardno 列的类型从activity 表中的CHAR(2) 转换为number(2))。

  • 不应重复主键列的值(此处 约束名称是activity_pk)

因此可以使用以下命令集:

drop table wizard;
drop table activity;
drop table group_; 

CREATE TABLE wizard (
    wizardno          NUMBER(2) NOT NULL,
    wizardname        VARCHAR2(30) NOT NULL
   );

ALTER TABLE wizard ADD CONSTRAINT wizard_pk PRIMARY KEY ( wizardno );
CREATE TABLE group_ (
    groupname        VARCHAR2(30) NOT NULL,
    activityno         NUMBER(2) NOT NULL
);

ALTER TABLE group_ ADD CONSTRAINT group_pk PRIMARY KEY ( groupname );


CREATE TABLE activity (
    activityno        NUMBER(2) NOT NULL,
    wizardno          NUMBER(2) NOT NULL,
    groupname         VARCHAR2(30)
);   

ALTER TABLE activity 
   ADD CONSTRAINT activity_pk PRIMARY KEY ( activityno );

ALTER TABLE activity
    ADD CONSTRAINT activity_wizard_fk FOREIGN KEY ( wizardno )
        REFERENCES wizard ( wizardno );
ALTER TABLE  activity
    ADD CONSTRAINT activity_group_fk FOREIGN KEY ( groupname )
        REFERENCES group_ ( groupname );
INSERT INTO wizard VALUES ( 77, 'Abc');
INSERT INTO wizard VALUES ( 99, 'Def');


INSERT INTO group_ VALUES ('the fellowship of the ring','01');
INSERT INTO activity VALUES ('01',77,'the fellowship of the ring');        
INSERT INTO activity VALUES ('02',99,'the fellowship of the ring'); 

【讨论】:

    【解决方案2】:
    • 不应将GROUP 关键字用作表名。相反,您可以将表名复数(wizardsgroupsactivities)。
    • wizardno 是向导表中的 NUMBER(2) 类型和活动表中的 CHAR(2),当它们之间存在外键引用时。它们应该是同一类型。
    • 您无需在活动表中复制groupname
    • 如果您不想在每个组中允许重复的向导,那么活动表上的主键应该是向导和组表的主键上的复合键。
    • 您可以使用序列来生成唯一的主键值。

    像这样:

    SQL Fiddle

    Oracle 11g R2 架构设置

    CREATE TABLE wizards (
      wizardno    NUMBER(2)
                  CONSTRAINT wizards_wizardno_pk PRIMARY KEY,
      wizardname  VARCHAR2(30)
                  CONSTRAINT wizards_wizardname_nn NOT NULL
    );
    
    CREATE SEQUENCE wizards_wizardno_seq;
    
    CREATE TABLE groups (
      groupname VARCHAR2(30)
                CONSTRAINT groups_groupname_u UNIQUE
                CONSTRAINT groups_groupname_nn NOT NULL,
      groupno   NUMBER(2)
                CONSTRAINT groups_groupno_pk PRIMARY KEY
    );
    
    CREATE SEQUENCE groups_groupno_seq;
    
    CREATE TABLE activities (
        activityno NUMBER(2)
                   CONSTRAINT activities_activityno_pk PRIMARY KEY,
        groupno    NUMBER(2)
                   CONSTRAINT activities_groupno_nn NOT NULL
                   CONSTRAINT activities_groupno_fk REFERENCES groups ( groupno ),
        wizardno   NUMBER(2)
                   CONSTRAINT activities_wizardno_nn NOT NULL
                   CONSTRAINT activities_wizardno_fk REFERENCES wizards ( wizardno ),
        CONSTRAINT activities_group_wizard_u UNIQUE ( groupno, wizardno )
    );   
    
    CREATE SEQUENCE activities_activityno_seq;
    
    INSERT INTO wizards ( wizardno, wizardname )
    VALUES ( wizards_wizardno_seq.NEXTVAL, 'Harry' );
    
    INSERT INTO wizards ( wizardno, wizardname )
    VALUES ( wizards_wizardno_seq.NEXTVAL, 'Gondor' );
    
    INSERT INTO groups ( groupname, groupno )
    VALUES ( 'the fellowship of the ring', groups_groupno_seq.NEXTVAL );
    
    INSERT INTO activities ( activityno, groupno, wizardno )
    VALUES ( activities_activityno_seq.NEXTVAL, 1, 1 );
    
    INSERT INTO activities ( activityno, groupno, wizardno )
    VALUES ( activities_activityno_seq.NEXTVAL, 1, 2 );
    

    查询 1

    SELECT wizardname,
           groupname
    FROM   wizards w
           INNER JOIN activities a
           ON ( w.wizardno = a.wizardno )
           INNER JOIN groups g
           ON ( a.groupno = g.groupno )
    

    Results

    | WIZARDNAME |                  GROUPNAME |
    |------------|----------------------------|
    |      Harry | the fellowship of the ring |
    |     Gondor | the fellowship of the ring |
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-09
      • 2016-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多