【问题标题】:Converting Traditional IF EXIST UPDATE ELSE INSERT into MERGE is not working?将传统的 IF EXIST UPDATE ELSE INSERT 转换为 MERGE 不起作用?
【发布时间】:2013-07-03 11:47:35
【问题描述】:

我将使用 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

【问题讨论】:

  • @MAri 你是什么意思?
  • 对于每个 DML 操作,您必须提交事务。那么只有你才能看到最新的数据..
  • @Mari 我没有任何交易
  • 这么简单的情况为什么要切换到MERGEThar be dragons,恕我直言。
  • @AaronBertrand,查看此链接,stackoverflow.com/questions/17039925/…

标签: tsql sql-server-2008-r2


【解决方案1】:

你的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;

【讨论】:

  • Jaochim,我需要一个通用的解决方案。其实我想转换我的传统如果不存在插入其他更新与合并
  • 我不确定你的意思,你需要在你的问题中添加更多细节才能回答。
【解决方案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);

【讨论】:

  • Damien,我需要一个通用的解决方案。其实我想转换我的传统如果不存在插入其他更新与合并
  • @user960567 - 我不确定您所说的“一般解决方案”是什么意思 - 我发布的是执行此操作的一般方法。您将 source 数据放在 USING 子句中 - 无论是文字,如上所示,还是针对其他表的查询。如果您想要更好的答案,请提供一些实际样本数据和预期结果。我显示的查询确实产生了您要求的结果。
  • 只有 1 个问题 damien?将上述语句放入事务(通常)有什么好处?
  • @user960567 - 每个 DML 语句都在事务中运行 - 无论您是否显式打开一个。如果您不打开一个,SQL Server 会自动打开一个,并且默认情况下,如果语句完成且没有错误,将提交它。还有一种替代模式(称为隐式事务),它会在语句完成时使事务保持打开状态,但默认情况下不启用。因此,如果您只是打算用BEGIN TRANSACTIONCOMMIT 包围上述代码,我会说不——因为SQL Server 已经在这样做了。
  • 此外,如果您真的要插入@table variable,那么您的交易并没有太多意义......
【解决方案3】:

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

SELECT id FROM @t WHERE ID = 2

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


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

【讨论】:

  • 我需要解决方案。如果不存在我需要插入并在存在时更新
【解决方案4】:

对于您必须提交的每个 DML 操作(标志着事务成功的结束)然后只有您才能看到最新数据

例如:

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

【讨论】:

  • 同样的结果。发帖前请自己这样做
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-18
  • 2014-04-27
  • 1970-01-01
  • 2011-04-11
  • 2012-09-08
  • 2021-08-30
相关资源
最近更新 更多