Вставьте 2 строки, которые связаны в обоих направлениях в SQL - PullRequest
3 голосов
/ 25 февраля 2010

У меня есть две таблицы вроде этого:

// 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, в которой есть ManagerID FK; за исключением моего случая таблицы были разделены.

РЕШЕНИЕ спасибо Ремусу Русану и 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

Ответы [ 5 ]

3 голосов
/ 25 февраля 2010

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

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

2 голосов
/ 25 февраля 2010

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

1 голос
/ 25 февраля 2010

Я бы лучше изменил дизайн БД. Таблицы не должны быть связаны таким образом. Imho.

0 голосов
/ 25 февраля 2010

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

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

0 голосов
/ 25 февраля 2010

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

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

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

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

...