使用循环引用SQL在TABLES中INSERT

时间:2013-04-14 14:02:24

标签: sql sql-insert create-table circular-reference

我有两张桌子:

Empleados(**numEmpl**, nombre, apellido, sexo, telefono, salario, numDept)
Departamentos(**numDept**, nombreDept, numDirect)

在出发中:

  1. numEmpl是主键
  2. numDept是Departamentos(numDept)的外键引用。 在detaamentos:
  3. numDept是主键
  4. numDirect是Empleados(numEmpl)的外键引用
  5. 所以有一个循环引用。

    首先我创建了表:

    CREATE TABLE EMPLEADOS(numEmpl primary key, nombre, 
         apellido, sexo, telefono, salario, numDept)
    CREATE TABLE DEPARTAMENTOS(numDept primary key, nombreDept, numDirect)
    (i didn't write here each of type is each colum)
    

    现在我在它们之间创建引用:

    ALTER TABLE DEPARTAMENTOS 
        ADD CONSTRAINT FK_DEPT_EMP FOREIGN KEY (numDirect) 
        REFERENCES EMPLEADOS(numEmpl)
    ALTER TABLE EMPLEADOS 
        ADD CONSTRAINT FK_EMP_DEPT FOREIGN KEY (numDept) 
        REFERENCES DEPARTAMENTOS(numDept).
    

    它有效,所以现在我尝试插入一些数据:

    INSERT INTO Empleados(numEmpl, nombre, apellidos, sexo, telefono, salario, numDept)
    VALUES (1, 'Pepito', 'Pérez', 'H', '111111111', 20000, 1);
    INSERT INTO Departamentos(numDept, nombreDept, numDirect)
    VALUES (1, 'Direccion', 1);
    

    但现在它抛出一个错误,告诉我我不能在循环引用中引入数据,我试图禁用循环引用并插入数据,然后再次启用它,它工作但有人告诉我它不是这是正确的方式,我必须做一些特别的事情,而我正在创建表格,以这种方式插入数据,它会工作,但我不知道如何做到这一点。 我顺便使用oracle sql developer。

    编辑:谢谢你的答案,但他们没有奏效。首先,我只能拥有那些表,当我进行插入时,必须以这种方式工作,不要将参数设为null然后更新它,对不起,我之前没有说过。 所以我必须这样做的唯一方法就是允许圆圈参考,但是当我尝试按照有人在这里说的方式做的时候,它会告诉我一些关于回滚的事情,有人可以提供帮助吗?

4 个答案:

答案 0 :(得分:5)

要允许循环引用,您需要可延迟的约束:

ALTER TABLE DEPARTAMENTOS 
    ADD CONSTRAINT FK_DEPT_EMP FOREIGN KEY (numDirect) 
    REFERENCES EMPLEADOS(numEmpl)
    DEFERRABLE INITIALLY DEFERRED
    ;
ALTER TABLE EMPLEADOS 
    ADD CONSTRAINT FK_EMP_DEPT FOREIGN KEY (numDept) 
    REFERENCES DEPARTAMENTOS(numDept)
    DEFERRABLE INITIALLY DEFERRED
    ;

交易结束时检查可延迟约束;在提交时间之前,允许存在虚假的无效数据库状态(在原始问题中:在两个插入语句之间)。但是语句必须在事务中,因此语句应该包含在BEGIN [WORK];COMMIT [WORK];中。

答案 1 :(得分:0)

循环引用很危险,导致您需要返回并更新数据,以使其不处于不一致状态。

如果您正处于计划阶段,我仍然建议您先考虑其他选项以避免这种情况,否则您可能会遇到很多麻烦。

http://blogs.msdn.com/b/sqlazure/archive/2010/07/01/10033575.aspx

如果您确实希望仍然使用它们,那么我建议在departments表上将NULL设置为允许值(这允许您插入一个没有d的新值),插入员工,然后返回并更新与员工ID。

答案 2 :(得分:0)

发生这种情况是因为在您为该员工创建Employees表中的记录(numEmpl = 1)之前,您无法在Department表中为numDirect创建值为1的记录。在创建部门记录之前,您无法创建员工。这可以通过使过程三步而不是仅两步来解决。要做到这一点,你必须能够创建没有numDirect FK值的Department记录,或者你必须能够创建没有numDept FK值的Employee。

说你决定后者。在这种情况下,在表NumDept中使EMPLEADOS为Nullable:

Alter table EMPLEADOS Alter Column numDept null

然后你可以:
首先,添加numDept

的空值的员工
INSERT Empleados(numEmpl, nombre, apellidos,
        sexo, telefono, salario, numDept)
VALUES (1, 'Pepito', 'Pérez', 'H', '111111111', 20000, null);

第二,添加员工:

INSERT Departamentos(numDept, nombreDept, numDirect)
VALUES (1, 'Direccion', 1);

最后,在部门记录中更新numDept的值。

Update Empleados Set numDept = 1 
Where numEmpl = 1

答案 3 :(得分:-1)

从您的出租表中取出numDirect列。该表应简单描述该部门。根据您的业务规则,您希望您拥有的离开和Empleados之间存在一对多的关系,或者它们之间存在多对多的关系。如果Empleado可以用于多个离开,那么您希望从Empleados表中删除numDept列并创建另一个表来设置多对多关系。

如果您设法找出使用当前设计添加记录的方法,那么您将遇到更大的问题。而不是只为每个部分记录一个记录,而是每个部分都需要一个记录。