Как я могу вставить набор дочерних записей при обновлении родительского? - PullRequest
2 голосов
/ 29 июля 2010

Я использую SQL Server 2005 и хочу создать номерные записи адресов, обновляя записи контактов новыми идентификаторами:

Возьмите следующие таблицы

create table contact(id int primary key identity, home_address_id int, work_address_id int)

create table address(id int primary key identity, street varchar(25), number int)

И внешние ключи:

ALTER TABLE dbo.contact ADD CONSTRAINT  FK_contact_address1 FOREIGN KEY (home_address_id) REFERENCES dbo.address(id)
ALTER TABLE dbo.contact ADD CONSTRAINT  FK_contact_address2 FOREIGN KEY (work_address_id) REFERENCES dbo.address(id)

некоторые фиктивные данные

insert into contact default values
insert into contact default values
insert into contact default values

Как мне вставить пустую запись адреса по умолчанию для всех контактов, у которых нет домашнего адреса, и обновить home_address_id за один раз?

Первая часть проста:

insert into address(street) select null from contact where home_address_id is null

Я даже могу получить новые идентификаторы адресов:

declare @addressTable table(id int)
insert into address(street) 
OUTPUT INSERTED.Id INTO @addressTable
select null from contact where home_address_id is null

Вот новый идентификатор

select * from @addressTable

Но как обновить таблицу контактов с помощью этих новых идентификаторов?

Ответы [ 2 ]

2 голосов
/ 29 июля 2010

Если возможно, я бы предложил нормализовать вашу базу данных, добавив таблицу Contact_Addresses:

CREATE TABLE Contact_Addresses
(
    contact_id INT NOT NULL,
    address_id INT NOT NULL,
    address_type VARCHAR(10) NOT NULL,
    CONSTRAINT PK_Contact_Addresses PRIMARY KEY CLUSTERED (contact_id, address_id, address_type),
    CONSTRAINT FK_ContactAddresses_Contacts (contact_id) REFERENCES Contacts (id),
    CONSTRAINT FK_ContactAddresses_Addresses (address_id) REFERENCES Addresses (id),
    CONSTRAINT CK_ContactAddresses_address_type CHECK address_type IN ('HOME', 'WORK')
)

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

Если вам действительно необходимо, то следующий код должен помочь:

;WITH C_CTE AS
(
    SELECT
        id,
        home_address_id,
        ROW_NUMBER() OVER(ORDER BY id) AS seq
    FROM
        Contacts
),
(
    SELECT
        id,
        ROW_NUMBER() OVER(ORDER BY id) AS seq
    FROM
        Addresses
)
UPDATE
    C_CTE
SET
    home_address_id = A.id
FROM
    C_CTE C
INNER JOIN A_CTE A ON A.seq = C.seq
1 голос
/ 29 июля 2010

Я бы сделал это с того момента, как вы получите новый контакт, таким образом:

[receive contact information]
//prior to inserting contact
declare @homeAddress int, @workAddress int

[insert home address here (real or default based on input)]
set @homeAddress = @@Identity

[insert work address here (real or default)]
set @workAddress = @@Identity

[insert contact here referencing @homeAddress & @workAddress]

Для вещей, которые уже есть в вашей таблице, вам нужно будет связать все ваши идентификаторы нулевого значения с идентификатором контакта. Или вы можете очистить адреса с нулевыми значениями и как-то изменить вышеприведенное выражение для обновления (мозг в данный момент не работает, поэтому все, что я придумываю, это курсор, а курсоры - зло).

...