5

我有 2 张桌子:

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

在部门:

  1. numEmpl 是主键
  2. numDept 是对 Departamentos(numDept) 的外键引用。在部门:
  3. numDept 是主键
  4. numDirect 是 Empleados (numEmpl) 的外键引用

所以有一个循环引用。

首先,我创建了表格:

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

4 回答 4

6

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

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
    ;

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

于 2013-04-14T14:16:37.233 回答
0

循环引用是危险的,它会导致您需要返回并更新您的数据,以免它处于不一致的状态。

如果您仍处于计划阶段,我敦促您查看其他选项以避免这种情况,否则您可能会遇到很多麻烦。

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

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

于 2013-04-14T14:19:10.737 回答
0

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

假设您决定后者。在这种情况下,NumDept在表中使 Nullable EMPLEADOS

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
于 2013-04-14T14:23:38.367 回答
-1

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

如果您设法找到一种方法来使用当前设计添加记录,那么您将遇到更大的问题。您需要为其中的每个 Empleado 制作一张唱片,而不是为每个 departamento 制作一张唱片。

于 2013-04-14T14:11:30.023 回答