如何将新生成的IDENTITY值插入到包含其他字段的相关表中?

时间:2017-07-26 15:03:22

标签: sql-server

我有一个包含姓名和社会安全号码的数据表。我想将名称插入带有标识字段的表中,然后将带有新标识字段值的ssn插入另一个表中。

以下是表格:

CREATE TABLE [data_table] 
(
    [name] [varchar](50) NOT NULL,
    [ssn] [varchar](9) NOT NULL,
)

CREATE TABLE [entity_key_table] 
(
    [entity_key] [int] IDENTITY(1000000,1) NOT NULL,
    [name] [varchar](50) NOT NULL,
)

CREATE TABLE [entity_identifier_table] 
(
    [entity_identifier_key] [int] IDENTITY(1000000,1) NOT NULL,
    [entity_key] [int] NOT NULL,
    [ssn] [int] NOT NULL,
)

此查询有效,但未将entity_key中的[entity_key_table]ssn中的[entity_identifier_table]相关联:

INSERT INTO entity_key_table (name)
OUTPUT [INSERTED].[entity_key]
INTO [entity_identifier_table] (entity_key)
    SELECT [name]
    FROM [data_table]

这是我想要做的,但它不起作用。

INSERT INTO entity (name)
OUTPUT [INSERTED].[entity_key], [data_table].[ssn]
INTO [entity_identifier] (entity_key,ssn)
    SELECT [name]
    FROM [data_table]

2 个答案:

答案 0 :(得分:0)

根据您的要求和您关联的文章重写我的答案。我认为你可以做这样的事情。我承认,我从来没有像文章所暗示的那样看到像1 != 1这样的东西的合并,所以我会对此非常谨慎,并测试它中的bajeeze。

FWIW,看起来在INSERT期间,您无法访问不在inserted虚拟表中但更新的数据(显然MERGE陈述)可以。

if object_id('tempdb.dbo.#data_table') is not null drop table #data_table
create table #data_table
(
    [name] [varchar](50) NOT NULL,
    [ssn] [varchar](9) NOT NULL,
)

if object_id('tempdb.dbo.#entity_key_table') is not null drop table #entity_key_table
create table #entity_key_table
(
    [entity_key] [int] IDENTITY(1000000,1) NOT NULL,
    name varchar(50)
)

if object_id('tempdb.dbo.#entity_identifier_table') is not null drop table #entity_identifier_table
create table #entity_identifier_table
(
    [entity_identifier_key] [int] IDENTITY(2000000,1) NOT NULL,
    [entity_key] [int] NOT NULL,
    [ssn] varchar(9) NOT NULL,
)
insert into #Data_table (Name, SSN)
select 'John', '123456789' union all
select 'John', '001100110' union all
select 'Jill', '987654321' 



merge into #entity_key_table t
using #data_table s
    on 1 != 1
when not matched then insert
(
    name   
)
values
(
    s.name
)
output inserted.entity_key, s.ssn
into #entity_identifier_table
(
    entity_key,
    ssn
);

select top 1000 *
from #data_table

select top 1000 *
from #entity_key_table

select top 1000 *
from #entity_identifier_table

答案 1 :(得分:0)

您的代码的问题是您只输出插入或删除的数据。

假设您的名称列仅与一个SSN相关,则以下内容将起作用:

DECLARE @output TABLE (entity_key INT,ssn VARCHAR (11))

INSERT INTO entity (entity_key, name)
OUTPUT [INSERTED].[entity_key], [inserted].[name]
INTO @output 
SELECT D.Entity_key, d.name 
FROM datatable

INSERT INTO entity_identifier (entity_key, ssn)
Select o.entity_key, d.snn
from @output o
join datatable d on o.name = d.name

但是,具有不同社会安全号码的多个重复名称的问题非常高。在这种情况下,您当前的结构根本不起作用,因为无法知道哪个标识属于哪个名称记录。 (另一篇文章中的合并解决方案也可能有这个问题,在你将其投入生产之前一定要测试重复名称的场景。在任何合理的大型名称数据集中,一组记录中重复名称的可能性非常高对于任何可能的解决方案,这应该是您的单元测试之一。)

这是一个潜在的解决方法。首先,在第一个插入中插入SSN作为名称,然后如图所示返回输出,但将@output Name列连接到SSN列。执行其他插入后,再将原始表中的名称更新为正确的名称,再次加入SSN数据。

DECLARE @output TABLE (entity_key INT,ssn VARCHAR (11))

INSERT INTO entity (entity_key, name)
OUTPUT [INSERTED].[entity_key], [inserted].[ssn]
INTO @output 
SELECT D.Entity_key, d.name 
FROM datatable

INSERT INTO entity_identifier (entity_key, ssn)
Select o.entity_key, d.output
from @output o


update e
set name = d.name
FROM entity e
join @output o on e.entity_key = o.entity_key
join datatable d on o.name = d.ssn