【问题标题】:How can I insert a set of child records while updating the parent?如何在更新父项时插入一组子记录?
【发布时间】:2010-07-29 13:46:18
【问题描述】:

我正在使用 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

这是新的身份证

select * from @addressTable

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

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      我会从你获得新联系人的那一刻开始,因此:

      [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 相关联。或者,您可以清除您的空值地址,并以某种方式将上述语句修改为更新(大脑目前不工作,所以我想出的只是一个游标,而游标是邪恶的)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-14
        • 1970-01-01
        • 2013-01-28
        • 1970-01-01
        相关资源
        最近更新 更多