2010-02-24 2 views
3

У меня есть две таблицы, вроде как это:Вставка 2 строки, которые связаны в обоих направлениях в SQL

// Person.Details Table: 
PersonID int [PK] | EmployeeCreatorID int [FK] | FirstName varchar | OtherInfo... 

// Employee.Details Table: 
EmployeeID int [PK] | PersonID int [FK] | IsAdmin bit | OtherInfo... 

Каждая таблица связана с другой:

[Employee.Details.PersonID]===>[Person.Details.PersonID] AND 
[Person.Details.EmployeeCreatorID]===>[Employee.Details.EmployeeID] 

через их внешние ключи.

Проблема заключается в том, что невозможно создать первого человека/сотрудника без удаления одного из ограничений внешних ключей, вставляя строки, а затем добавляя ограничение (в котором довольно слабо).

Очевидный Божий парадокс здесь заключается в том, что первого «Работника» не существует, чтобы создать себя («Личность»).

Есть ли способ одновременно вставлять данные в две таблицы? Этот сценарий созданного-создателя должен произойти только один раз. Если я не могу вставить данные в две таблицы одновременно, есть ли какие-либо другие методы, которые вы, г-н Гении, предлагаете?

РАЗЪЯСНЕНИЕ

Есть другие таблицы, связанные с таблицей «Лицо» ... как «Студенты» и «Хранители». Человек не может переключать типы (Employee не может переключиться на Student или Guardian, а также на визу). Парадокс похож на таблицу Employee, в которой есть ManagerID FK; кроме как в моем случае таблицы были разделены.

РЕШЕНИЕ благодаря Remus Ruşanu и b0fh

--/*seeds database with first employee*/ 
BEGIN TRAN 
GO 
INSERT INTO Person.Details 
    (EmployeeCreatorID, FirstName, Active) 
VALUES 
    (@@Identity, 'Admin', 1) 
DECLARE @Identity int; 
SET @Identity = @@Identity; 
INSERT INTO Employee.Details 
    (PersonID, IsAdmin, Email, Password) 
VALUES 
    (@Identity, 1, 'admin', 'admin') 
UDPATE 
    Person.Details 
SET 
    EmployeeCreatorID = @@Identity 
WHERE 
    PersonID = @Identity 

IF(@@ERROR <> 0) 
    ROLLBACK TRAN 
ELSE 
    COMMIT TRAN 
+1

Никогда не используйте @@ identity. Очень плохая практика для целостности данных. Вы находитесь в 2008 году, поэтому используйте выходную команду или scope_identity(). @@ identity выдаст неверные значения, если кто-либо когда-либо помещает триггер в вашу таблицу, который вставляет в другую таблицу с столбцом идентификации, очень опасно использовать. – HLGEM

+0

+1 В моем случае я думаю, что SCOPE_IDENTITY() будет лучшим выбором; предложение OUTPUT будет немного выше верхнего правого? –

ответ

3

Ключ NULL будет передавать ограничение внешнего ключа. Вы можете вставить Person с NULL CreatorID, и это станет великим папой всей иерархии.

Вы также можете вставить отключить ограничение, вставить первую пару (Person, Employee), которая указывает друг на друга, а затем включить обратно ограничение, и с этого момента система засевается.

+0

Я установил значение null в столбце CreatorID, поэтому он не работал. Спасибо за Ваш ответ! –

+0

Вы действительно хотите, чтобы нулевой создатель, если это не так, поражает цель столбца? Во-вторых, должен ли человек создавать себя? – awright18

2

Не уверен, что сервер SQL, но и в других СУБД я знаю, вы можете сделать это до тех пор, как два шага в одной транзакции. Просто оберните два утверждения между BEGIN; и COMMIT;.

0

Модель выглядит ошибочной для меня, но я думаю, вам, возможно, просто нужно объяснить требования лучше. До сих пор:

  • Каждое лицо создано Работником.
  • Сотрудник - это человек.

Есть ли люди, которые не являются сотрудниками? Почему они находятся в системе? Возможно ли, чтобы Лицо переключилось с того, чтобы быть Работником, чтобы не быть Работником, или наоборот?

Хотя я думаю, что лучший ответ может возникнуть, когда вы сможете ответить на вышеуказанный вопрос. Одно из предложений заключается в том, чтобы изменить EmployeeCreaterId на PersonCreatorId и иметь вторичное (не принудительное использование схемы базы данных) требование о том, что PersonCreatorId является сотрудником.

1

Я предпочел бы изменить дизайн db. Таблицы не должны быть связаны таким образом imho.

+0

Я думал то же самое, когда понял, что у меня будет эта проблема. Однако я понял, что проблема не сильно отличается от таблицы Employee Table с FID ManagerID, которая относится к ПК EmployeeID менеджера (в той же таблице). Если вы видите какие-либо проблемы/осложнения, которые могут возникнуть в результате этого проекта, я был бы очень любезен, если вы меня наполнили. :-) –

0

У вас должен быть только один сотрудник для создания людей, которые могут или не могут быть сотрудниками. Единственная проблема заключается в том, что работник не может создать себя. Поэтому я хотел бы предложить, прежде чем вводить первого человека в базу данных, вы убедитесь, что employeeeecreatorid fk не является обязательным. Затем создайте человека. Затем создайте запись сотрудника для этого связанного лица. Поскольку у вас есть человек, вы можете потребовать personID FK в таблице employee, и он будет существовать. Затем обновите исходную настройку записи персонажа EmployeeCreatorId, равную вновь созданному EmployeeID. . Затем установите столбец EmployeeCreatorID FK в таблице лиц обратно в требуемый.
Теперь вы должны убедиться, что новые люди созданы только текущими сотрудниками, которые не будут создаваться человеком.

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

Смежные вопросы