我有一个包含姓名和社会安全号码的数据表。我想将名称插入带有标识字段的表中,然后将带有新标识字段值的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]
答案 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