2013-04-14 3 views
3

У меня есть 2 таблицы:ВСТАВИТЬ в таблицах с циклическими ссылками SQL

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

In Departamentos:

  1. numEmpl является первичным ключом
  2. numDept является внешним ключом ссылкой на Departamentos (numDept). В Departamentos:
  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.

EDIT: Спасибо за ответы, но они не сработали. Прежде всего, я могу только иметь эти таблицы, и когда я делаю вставку, она ДОЛЖНА работать таким образом, не делая параметр null, а затем обновляю его, извините, что я не говорил об этом раньше. Итак, единственный способ, которым я должен это сделать, это позволить ссылку на круг, но когда я пытаюсь сделать это так, как кто-то сказал здесь, это говорит мне что-то об откате, кто-то может помочь?

ответ

4

Чтобы разрешить циклические ссылки, вам необходимо откладываемые ограничения:

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];.

+0

Sql Server удалил параметр DEFERRABLE несколько версий назад, только Oracle имеет его. – Brent

+0

У них тоже есть Postgres. (по какой-то причине, я полагаю), я не знаю, находятся ли они в ANSI, я полагаю, что они есть. BTW: вопрос есть/был помечен SQL, а не SQL-сервером. – wildplasser

+0

Да, это нормально, этот вопрос просто получил мои надежды, и комментарий, который не работает в Sql Server, спас меня некоторое время. – Brent

0

Возьмите столбец numDirect из таблицы ваших столбов. Эта таблица должна просто описать отдел. В зависимости от ваших бизнес-правил вы хотите иметь отношения между многими девальонами и Empleados, которые у вас есть, или отношения многих и многих между ними. Если Empleado может работать более чем на один декаменто, вы хотите сбросить столбец numDept из таблицы Empleados и создать еще одну таблицу, чтобы настроить отношения многих и многих.

Если вам удастся выяснить способ добавления записей с вашим текущим дизайном, у вас будет большая проблема. Вместо того, чтобы иметь только одну запись для каждого декаменто, вам понадобится один для каждого Empleado.

0

Циркулярные ссылки опасны и заставляют вас возвращаться и обновлять свои данные, чтобы они не находились в противоречивом состоянии.

Если вы находитесь на своих этапах планирования, я настоятельно призываю вас взглянуть на другие варианты, чтобы избежать этого, иначе вы можете столкнуться с множеством головных болей в будущем.

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

Если вы хотите использовать их по-прежнему, то я хотел бы предложить создание NULL в качестве допустимого значения по таблице отделов (это позволяет вставить новое значение не г), Установка сотрудника, а затем вернуться и обновить идентификатор сотрудника.

0

Это происходит потому, что вы не можете создать запись в таблице Департамента со значением 1 для numDirect, пока не создадите запись в таблице Employees для этого сотрудника (numEmpl = 1). И вы не можете создать сотрудника, пока не создадите его запись отдела. Это решается путем выполнения процесса тремя шагами вместо двух. Для этого вы должны иметь возможность создать запись отдела без значения numDirect FK или у вас есть возможность создать Employee без значения 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