如何在更新父级时插入一组子记录?

时间:2010-07-29 13:46:19

标签: sql sql-server-2005 sql-update parent

我正在使用SQL Server 2005并希望创建一个数字地址记录,用新的Id更新联系人记录:

采取以下表格

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

我甚至可以获得新创建的地址ID:

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

这是新的ID

select * from @addressTable

但是如何用这些新的Id更新联系人表?

2 个答案:

答案 0 :(得分:2)

如果可能,我建议通过添加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')
)

接下来,我建议不要在数据库中放入“虚拟”记录。它最终会导致头痛。数据库应包含系统中数据的准确记录。如果要在联系人系统中不存在地址时默认显示某个值,请在UI中处理该地址。

如果你真的必须这样做,那么下面的代码可以解决这个问题:

;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 :(得分:1)

从你收到新联系的那一刻起我就会这样做:

[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]

对于表中已有的内容,您必须将所有空值id与联系人ID相关联。或者,你可以清除你的空值地址,并以某种方式将上述语句修改为更新(大脑此刻不起作用,所以我想出的只是一个游标,而游标是邪恶的)。