【问题标题】:TSQL Merge 2 Ids into Temp TableTSQL 将 2 个 ID 合并到临时表中
【发布时间】:2017-04-27 15:24:48
【问题描述】:

我正在 SQL Server 2012 上的 TSQL 中处理存储过程。当我调用存储过程时。我的问题:我将值插入到表 Projects 中,并希望将导入表中的 inserted.ProjectIdoID 一起存储到临时表中;我不会将导入表中的oID 存储到Projects 表中。

我指的是这个答案: Insert Into... Merge... Select (SQL Server)

1) 导入表:我正在将一个表从 C# 发送到 SQL,其中包含以下值:

oID |  Title   | 
----+----------+
 0  | ProjectX |
 1  | ProjectY |
 2  | ProjectZ |

在存储过程中是这样的:

CREATE TYPE [MySchema].[Project] AS TABLE
(
    oID INT,
    Title VARCHAR(100)
);

@ImportProjects MySchema.Project READONLY

2) Projects Table:我正在将值插入到 Table Projects 中,并希望将插入的 ProjectId 以及导入表中的 oID 存储到临时表中: p>

ProjectId |  Title   | 
----------+----------+
33        | ProjectX |
34        | ProjectY |
35        | ProjectZ |

3) Desired Output, Temporary Table:在我的临时表中,我想存储 ProjectId 以及导入表中的 oID:

 RowID  | oID |  ProjectId   | 
--------+-----+--------------+
1       |  0  | 33           |
2       |  1  | 34           |
3       |  2  | 35           |

我的合并查询如下所示:

create table Temp (ProjectId INT, oID INT)

MERGE INTO Temp USING
(
    SELECT 
        a.oID as oID,
        b.ProjectId as ProjectId
    FROM @ImportProjects a
    CROSS JOIN Projects b
) AS s ON 1 = 0
WHEN NOT MATCHED THEN
INSERT (oID, ProjectId)
VALUES (s.oID, s.ProjectId)
OUTPUT Inserted.ProjectId, s.oID
INTO Temp(oID, ProjectId);

这真的不起作用...我的问题之一当然是交叉连接,但我在导入表和项目表之间没有链接或外键...

你知道如何实现吗?

谢谢!! :)

【问题讨论】:

  • Project.Title unique?
  • 不幸的是……这只是一个简单的 varchar(100)
  • 您的Project 表中是否有一组列唯一标识ProjectId 以外的行?
  • 在我的项目表中,我只有主键 ProjectId ProjectId INT IDENTITY(1,1)

标签: sql sql-server tsql


【解决方案1】:

您的merge 尝试有点令人困惑,但我认为这是您想要的:

create table tvp (oid int, Title varchar(100));
insert into tvp values (0,'ProjectX'),(1,'ProjectY'),(2,'ProjectZ');

create table #tmp (
    Id int not null identity(1,1)
  , oid int
  , ProjectId int
  , Title varchar(100)
);
create table Project (
    ProjectId int not null identity(33,1)
  , Title varchar(100)
);

merge into Project as Target
using tvp as Source
  on 1 = 0
when not matched then
insert (Title)
  values (source.Title)
output source.oid, Inserted.ProjectId, Inserted.Title
into #tmp;

select * from #tmp;

rextester 演示:http://rextester.com/PIRFA34601

返回:

+-----+-----+-----------+----------+
|  Id | oid | ProjectId |  Title   |
+-----+-----+-----------+----------+
|   1 |   0 |        33 | ProjectX |
|   2 |   1 |        34 | ProjectY |
|   3 |   2 |        35 | ProjectZ |
+-----+-----+-----------+----------+

Rextester 不支持表类型(因为不能在同一个事务中声明和使用),所以我改用了表tvp

【讨论】:

  • 酷,非常感谢这个详细的例子! ...真正的优势是我不必加入标题! :)
  • @TimHorton 乐于助人!
【解决方案2】:

CROSS JOIN 替换为INNER JOIN。内连接不需要外键

create table Temp (ProjectId INT, oID INT)

MERGE INTO Temp USING
(
    SELECT 
        a.oID as oID,
        b.ProjectId as ProjectId
    FROM @ImportProjects a
    INNER JOIN JOIN Projects b ON a.Title = b.Title
) AS s ON 1 = 0
WHEN NOT MATCHED THEN
INSERT (oID, ProjectId)
VALUES (s.oID, s.ProjectId)
OUTPUT Inserted.ProjectId, s.oID
INTO Temp(oID, ProjectId);

【讨论】:

  • 感谢米哈伊尔,但不幸的是它似乎不起作用,它产生 6 行而不是 3 行......嗯
  • 这是因为合并。 WHEN NOT MATCHED 语句插入 3 行,OUTPUT INTO 语句插入另外 3 行。使用简单的INSERT INTO 或将输出插入另一个表
猜你喜欢
  • 1970-01-01
  • 2023-03-26
  • 2019-04-06
  • 1970-01-01
  • 2018-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多