一次性将数据拆分成两个表

5 sql-server-2008 sql-server t-sql

我正在使用 SQL Server 2008 并且有一个问题,如果不使用许多临时表和不可靠的连接,我不知道如何解决。

表 1 包含 6 列数据,然后将其拆分为两个表。Col1 到 Col3 进入表 2,Col4 到 Col6 进入表 3。将数据放入表 2 和表 3 是容易的部分。然而,表 3 中的 T2ID 是表 2 中 ID 的外键。

性能是关键,所以我不想使用变量和/或逐行迭代数据,理想情况下,我只想要一个可以做很多事情的插入。

我曾尝试使用链接表,但表 2 和表 3 中的数据不是唯一的,这使得连接不可靠。

有什么建议?

Create Table T1 (
  ID INT IDENTITY(1,1),
  Col1 VARCHAR(10),
  Col2 VARCHAR(10),
  Col3 VARCHAR(10),
  Col4 VARCHAR(10),
  Col5 VARCHAR(10),
  Col6 VARCHAR(10)
)

Create Table T2 (
  ID INT IDENTITY(1,1),
  Col1 VARCHAR(10),
  Col2 VARCHAR(10),
  Col3 VARCHAR(10)
)

Create Table T3 (
  ID INT IDENTITY(1,1),
  T2ID INT,
  Col4 VARCHAR(10),
  Col5 VARCHAR(10),
  Col6 VARCHAR(10)
)
Run Code Online (Sandbox Code Playgroud)

我不能改变T2或T3。T1 不是临时表,我也无法更改。还有其他包也写入 T1、T2 和 T3。尽管可以在需要时在不同时间安排它们。

And*_*y M 6

如果使用 MERGE 将数据插入到 中T2,则可以在T1.ID和之间生成映射表T2.ID

DECLARE @Mapping TABLE
(
  T1ID int,
  T2ID int
);
MERGE INTO
  dbo.T2 AS tgt
USING
  dbo.T1 AS src
ON
  1 = 0
WHEN NOT MATCHED THEN
  INSERT (    Col1,     Col2,     Col3)
  VALUES (src.Col1, src.Col2, src.Col3)
OUTPUT
  src.ID, inserted.ID INTO @Mapping (T1ID, T2ID)
;
Run Code Online (Sandbox Code Playgroud)

与 INSERT 允许您inserted仅在 OUTPUT 子句中引用表的列不同,MERGE 语句也允许您引用源表的列。这是此解决方案的关键,因为这是将源 ID 与目标 ID 关联的方式。

一旦你有了映射表,你就可以在插入时在连接中使用它T3INSERT ... SELECT这一次,一个平原会这样做:

INSERT INTO
  dbo.T3 (T2ID, Col4, Col5, Col6)
SELECT
  m.T2ID,
  t.Col4,
  t.Col5,
  t.Col6
FROM
  dbo.T1 AS t
  INNER JOIN @Mapping AS m ON t.ID = m.T1ID
;
Run Code Online (Sandbox Code Playgroud)

将两个语句包装在一个事务中,以使拆分操作具有原子性。

可以在此线程中找到有关 MERGE 映射方法的讨论: