简体   繁体   English

SQL 数据库未启动,因为主键

[英]SQL database is not starting because primary keys

SQL database won't initialize because all tables rely on primary keys/foreign keys that are in different tables. SQL 数据库不会初始化,因为所有表都依赖于不同表中的主键/外键。 Is there a way to get this to compile and not break?有没有办法让它编译而不破坏?

Attached is code and ERD schema附件是代码和 ERD 架构

ERD ERD

CREATE TABLE boat 
(
    huID int NOT NULL,
    manufacturer varchar(50) NOT NULL,
    Model varchar(20) NOT NULL,
    Year int NOT NULL,
    Price decimal(5,2) NOT NULL,
    color varchar(30) NOT NULL,
    condition varchar(20),
    CHECK (condition = 'New' OR condition = 'Used') ,

    CONSTRAINT boat_huID_fk 
        FOREIGN KEY (huID) REFERENCES Holding(huID),
    CONSTRAINT boat_Price_pk PRIMARY KEY (Price)
);

CREATE TABLE Customer 
(
    customerID int,
    Name varchar(50) PRIMARY KEY,
    Address varchar(50) NOT NULL,
    Phone int NOT NULL,

    CONSTRAINT Customer_customerID_fk 
        FOREIGN KEY (customerID) REFERENCES invoice(customerID)
);

CREATE TABLE Holding
(
    huID int NOT NULL,

    CONSTRAINT boat_huID_pk PRIMARY KEY (huID)
);

CREATE TABLE Salesperson 
(
    salespersonID int PRIMARY KEY,
    Name varchar(50) NOT NULL,

    CONSTRAINT Customer_Name_fk 
        FOREIGN KEY (Name) REFERENCES Customer (Name) 
);

CREATE TABLE invoice 
(
    invoiceNumber int,
    customerID int NOT NULL,
    salespersonID int,
    Price int NOT NULL,
    huID int NOT NULL
        CONSTRAINT boat_huID_fk REFERENCES Holding(huID),

    CONSTRAINT boat_Price_pk 
        FOREIGN KEY (Price) REFERENCES boat(Price),
    CONSTRAINT Salesperson_salespersonID_fk 
        FOREIGN KEY (salespersonID) REFERENCES Salesperson (salespersonID),
    CONSTRAINT Customer_customerID_pk PRIMARY KEY(customerID)
);

When you have circular foreign key constraints, define one constraint of the circle separately using an ALTER .当您有循环外键约束时,请使用ALTER分别定义一个循环约束。

The pattern is:模式是:

CREATE TABLE T1 (
  ID INT PRIMARY KEY,
  ... -- other cols
);

CREATE TABLE T2 (
  ID INT PRIMARY KEY,
  ..., -- other cols
  CONSTRAINT T1_FK FOREIGN KEY (ID) REFERENCES T1(ID)
);

Create other tables with FKs to previously defined tables.使用 FK 为先前定义的表创建其他表。

Then complete the circle with an FK from the first table to the last table via an ALTER :然后通过ALTER用 FK 从第一个表到最后一个表完成圆圈:

ALTER TABLE T1 ADD CONSTRAINT T2_FK FOREIGN KEY (ID) REFERENCES T2(ID);

Alternatively, if it's too hard to keep track of what depends on what, you can just define all foreign keys using ALTER .或者,如果很难跟踪什么取决于什么,您可以使用ALTER定义所有外键。

You'll have to create tables in order so that tables - that reference other tables - aren't created before them.您必须按顺序创建表,以便不会在它们之前创建引用其他表的表。

In your case,在你的情况下,

  • reordering CREATE TABLE statements,重新排序CREATE TABLE语句,
  • removing foreign key constraint from salesperson (not entirely; create it with alter table at the end of the script) andsalesperson中删除外键约束(不完全;在脚本末尾使用alter table创建它)和
  • renaming constraints in salesperson table (you named them in a strange manner, not uniquely)重命名salesperson表中的约束(您以一种奇怪的方式命名它们,而不是唯一的)

does the job.做这项工作。

SQL> CREATE TABLE holding (
  2      huid INT NOT NULL,
  3      CONSTRAINT boat_huid_pk PRIMARY KEY ( huid )
  4  );

Table created.

SQL>
SQL> CREATE TABLE boat (
  2      huid         INT NOT NULL,
  3      manufacturer VARCHAR(50) NOT NULL,
  4      model        VARCHAR(20) NOT NULL,
  5      year         INT NOT NULL,
  6      price        DECIMAL(5, 2) NOT NULL,
  7      color        VARCHAR(30) NOT NULL,
  8      condition    VARCHAR(20),
  9      CHECK ( condition = 'New'
 10              OR condition = 'Used' ),
 11      CONSTRAINT boat_huid_fk FOREIGN KEY ( huid )
 12          REFERENCES holding ( huid ),
 13      CONSTRAINT boat_price_pk PRIMARY KEY ( price )
 14  );

Table created.

SQL>
SQL> CREATE TABLE salesperson (
  2      salespersonid INT PRIMARY KEY,
  3      name          VARCHAR(50) NOT NULL
  4  --    CONSTRAINT Customer_Name_fk
  5  --        FOREIGN KEY (Name) REFERENCES Customer (Name)
  6  );

Table created.

SQL>
SQL> CREATE TABLE invoice (
  2      invoicenumber INT,
  3      customerid    INT NOT NULL,
  4      salespersonid INT,
  5      price         INT NOT NULL,
  6      huid          INT NOT NULL
  7          CONSTRAINT inv_huid_fk
  8              REFERENCES holding ( huid ),
  9      CONSTRAINT inv_price_pk FOREIGN KEY ( price )
 10          REFERENCES boat ( price ),
 11      CONSTRAINT salesperson_salespersonid_fk FOREIGN KEY ( salespersonid )
 12          REFERENCES salesperson ( salespersonid ),
 13      CONSTRAINT customer_customerid_pk PRIMARY KEY ( customerid )
 14  );

Table created.

SQL>
SQL> CREATE TABLE customer (
  2      customerid INT,
  3      name       VARCHAR(50) PRIMARY KEY,
  4      address    VARCHAR(50) NOT NULL,
  5      phone      INT NOT NULL,
  6      CONSTRAINT customer_customerid_fk FOREIGN KEY ( customerid )
  7          REFERENCES invoice ( customerid )
  8  );

Table created.

SQL>
SQL> ALTER TABLE salesperson
  2      ADD CONSTRAINT customer_name_fk FOREIGN KEY ( name )
  3          REFERENCES customer ( name );

Table altered.

SQL>

In addition, to the above mentioned comments you may want to add in the cascade clause so if you delete a parent row all the related underlying rows will also be removed.此外,您可能希望在 cascade 子句中添加上述注释,因此如果您删除父行,所有相关的底层行也将被删除。 Below is a test case.Use with caution.下面是一个测试用例,请谨慎使用。

In addition, I also provided a query that you may want to use to tell you what is related.此外,我还提供了一个查询,您可能想用它来告诉您什么是相关的。 In my example, I hardcoded the table name ''PARENT" but you may want to use a bind variable. Good Luck.在我的示例中,我对表名“PARENT”进行了硬编码,但您可能希望使用绑定变量。祝你好运。


create table parent (
  id NUMBER(10),
  value      varchar2(30),
constraint parent_pk primary key (id)
);

CREATE TABLE child
( id NUMBER(10) not null,
value NUMBER(10) not null,
constraint child_pk primary key (id,value),
CONSTRAINT parent_child_fk
FOREIGN KEY (id)
REFERENCES parent(id)
ON DELETE CASCADE
);

CREATE TABLE grandchild
( id NUMBER(10) not null,
value NUMBER(10) not null,
constraint grandchild_pk primary key (id,value),
CONSTRAINT child_grandchild_fk
FOREIGN KEY (id,value)
REFERENCES child(id,value)
ON DELETE CASCADE
);


insert into parent values (1,'a');
insert into parent values (2,'b');
insert into parent values (3,'c');

insert into child  values (1,1);
insert into child  values (1,2);
insert into child  values (1,3);
insert into child  values (2,1);
insert into child  values (2,2);
insert into child  values (2,3);
insert into child  values (3,1);
insert into child  values (3,2);
insert into child  values (3,3);

insert into grandchild  values (1,1);
insert into grandchild  values (1,2);
insert into grandchild  values (1,3);
insert into grandchild  values (2,1);
insert into grandchild  values (2,2);
insert into grandchild  values (2,3);
insert into grandchild  values (3,1);
insert into grandchild  values (3,2);
insert into grandchild  values (3,3);

SELECT  (
        SELECT COUNT(*)
        FROM   parent 
        ) AS parent_cnt,
       (
        SELECT COUNT(*)
        FROM   child 
        ) AS child_cnt,
        (
        SELECT COUNT(*)
        FROM   grandchild
        ) AS grandchild_cnt
FROM    dual

PARENT_CNT    CHILD_CNT    GRANDCHILD_CNT
3    9    9

DELETE from parent where value = 'a';


SELECT  (
        SELECT COUNT(*)
        FROM   parent 
        ) AS parent_cnt,
       (
        SELECT COUNT(*)
        FROM   child 
        ) AS child_cnt,
        (
        SELECT COUNT(*)
        FROM   grandchild
        ) AS grandchild_cnt
FROM    dual

PARENT_CNT    CHILD_CNT    GRANDCHILD_CNT
2    6    6

Here is a query you can use to show the relationships

with f as (
        select constraint_name, table_name, r_constraint_name
        from   user_constraints
        where  constraint_type = 'R'
     ),
     p as (
        select constraint_name, table_name
        from   user_constraints
        where  constraint_type = 'P'
     ),
     j (child_table, f_key, parent_table, p_key) as (
        select f.table_name, f.constraint_name, p.table_name, f.r_constraint_name
        from   p join f on p.constraint_name = f.r_constraint_name
        union all
        select 'PARENT', (select constraint_name from p                                where table_name = 'PARENT'), null, null from dual
     )
select level as lvl, j.*
from j
start with parent_table is null
connect by nocycle parent_table = prior child_table
order by lvl, parent_table, child_table;

LVL    CHILD_TABLE    F_KEY    PARENT_TABLE    P_KEY
1    PARENT    PARENT_PK     -      - 
2    CHILD    PARENT_CHILD_FK    PARENT    PARENT_PK
3    GRANDCHILD    CHILD_GRANDCHILD_FK    CHILD    CHILD_PK

So now when we delete from parent Oracle will check if there are tables with FKs referencing parent and will find table child.所以现在当我们从父 Oracle 删除时,将检查是否有 FK 引用父表的表,并会找到表子表。 Then it will check one-by-one if to be deleted table parent row has children in table child.然后它将一一检查要删除的表父行是否在表子中具有子行。 If not it will delete that table parent row.如果不是,它将删除该表父行。 If there are children if will check FK action and since that FK has ON DELETE CASCADE Oracle will try to delete that table child row.如果有孩子 if 将检查 FK 操作,并且由于该 FK 具有 ON DELETE CASCADE Oracle 将尝试删除该表的子行。 At that point it will (same as with table parent) check if there are tables with FKs referencing table child and will find table grandchild.那时它将(与表父表相同)检查是否有 FK 引用表子表的表,并会找到表孙子表。 Same way it will check one-by-one if to be deleted table child row has children in table grandchild.同样,如果要删除的表子行在表孙子中是否有子项,它将一一检查。 If not it will delete that table child row.如果不是,它将删除该表子行。 If there are children if will check FK action and since that FK has ON DELETE CASCADE Oracle will try to delete that table grandchild row.如果有孩子 if 将检查 FK 操作,并且由于该 FK 具有 ON DELETE CASCADE Oracle 将尝试删除该表的孙行。 Since table grandchild has no child tables Oracle will delete corresponding rows in tables grandchild, child and then parent.由于表 grandchild 没有子表 Oracle 将删除表中的相应行孙子,子,然后父。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM