将传统的IF EXIST UPDATE ELSE INSERT转换为MERGE不起作用?

时间:2013-07-03 11:47:35

标签: tsql sql-server-2008-r2

我将使用MERGE来插入或更新表,具体取决于它是否存在。这是我的查询,

declare @t table
(
    id int,
    name varchar(10)
)
insert into @t values(1,'a')

MERGE INTO @t t1
USING (SELECT id FROM @t WHERE ID = 2) t2 ON (t1.id = t2.id)
WHEN MATCHED THEN
    UPDATE SET name = 'd', id = 3
WHEN NOT MATCHED THEN
    INSERT (id, name)
    VALUES (2, 'b');

select * from @t;

结果是,

id  name
1   a

我认为应该是,

id  name
1   a
2   b

4 个答案:

答案 0 :(得分:3)

你的USING部分有些混乱,这就是你想要匹配的内容(尽管在这种情况下你只使用id

declare @t table
(
    id int,
    name varchar(10)
)

insert into @t values(1,'a')

MERGE INTO @t t1
USING (SELECT 2, 'b') AS t2 (id, name) ON (t1.id = t2.id)
WHEN MATCHED THEN
    UPDATE SET name = 'd', id = 3
WHEN NOT MATCHED THEN
    INSERT (id, name)
    VALUES (2, 'b');

select * from @t;

答案 1 :(得分:2)

正如Mikhail指出的那样,USING子句中的查询不包含任何行。

如果要进行upsert,请将新数据放入USING子句:

MERGE INTO @t t1
USING (SELECT 2 as id, 'b' as name) t2 ON (t1.id = t2.id) --This no longer has an artificial dependency on @t
WHEN MATCHED THEN
    UPDATE SET name = t2.name
WHEN NOT MATCHED THEN
    INSERT (id, name)
    VALUES (t2.id, t2.name);

答案 2 :(得分:1)

此查询不会返回任何内容:

SELECT id FROM @t WHERE ID = 2

因为ID = 2的表中没有行,所以没有任何内容可以合并到表中。


此外,在MATCHED子句中,您正在更新您正在加入表的字段ID,我认为这是禁止的。

答案 3 :(得分:0)

对于您必须提交的每个DML操作(标记成功交易的结束)然后只有您将能够看到最新数据

例如:

GO
BEGIN TRANSACTION;
GO
DELETE FROM HumanResources.JobCandidate
    WHERE JobCandidateID = 13;
GO
COMMIT TRANSACTION;
GO