在 SQL Server 2005 的查询中与 T-SQL 进行数据比较

Posted

技术标签:

【中文标题】在 SQL Server 2005 的查询中与 T-SQL 进行数据比较【英文标题】:Doing a data compare with T-SQL in a query in SQL Server 2005 【发布时间】:2010-02-26 07:14:38 【问题描述】:

我想知道是否有人知道这样做的简单方法。

我有几个包含数据的表,这些数据是“静态的”,用户不会更改它,只有我可以插入/更新行。 我想知道是否有一种简单的方法可以插入不存在的行并更新不同的行。

我认为可行的方法是:

IF((SELECT COUNT(*) FROM myTable WHERE myId = x) = 0)
   INSERT myTable() values()
ELSE
   UPDATE myTable SET data = updatedData WHERE myId = 0

但由于我有很多行要更新,我想知道是否有更简单的方法来做到这一点。 VS 数据库中有一个数据比较器,是否可以通过查询脚本或其他方式以某种方式使用它? 我希望在使用 VS 部署数据库项目时完成这些更新。

【问题讨论】:

【参考方案1】:

您可以在数据库上触发自动更新/插入行。

【讨论】:

你的意思是触发器检查记录是否存在,如果存在则更新,如果不存在则插入? 这似乎正是我想要的。非常感谢! 用于连接 XPathNavigator nav = listXml.CreateNavigator(); XmlNamespaceManager nsmgr = new XmlNamespaceManager(nav.NameTable); nsmgr.AddNamespace("trd", "tridion.com/ContentManager/5.0"); XPathExpression expr; expr = nav.Compile("//trd:Item/@Title | //trd:Item/@ID"); expr.SetContext(nsmgr) ;【参考方案2】:

您可以轻松删除 if 语句,如下所示:

insert into myTable
select
   <values>
where
   not exists(select * from myTable where myId = @x)

然后,您可以检查@@rowcount 的值。如果它不为零,那么您可以退出该部分逻辑,知道记录已输入到数据库中。

如果@@rowcount为零,则表示该id的记录存在于数据库中,您可以发出更新:

update 
    myTable 
set 
    <values>
where 
    myId = @x

请注意,您要确保它在事务中运行,因为如果您尝试从两个单独的客户端更新此代码,可能会出现竞争条件。

【讨论】:

嗯...这是一个更好看的查询。 :) 但这并没有解决我真正的问题,我仍然必须为每条记录编写这两个查询。我希望有一个更“自动”的解决方案。 :) +1。当然,您可以先触发更新,然后触发插入。如果该行不存在,则不会更新任何内容。只有在该行不存在时才会发生插入。您可能会因为编写稍微少一点的代码而对性能造成很小的影响,但可能值得(当然,如果您要比较的列被正确索引!) @Markus:这真的是你能得到的最好的。如果您使用的是 SQL Server 2008,则可以使用 MERGE 命令,正如@MPritch 在他的回答中指出的那样:***.com/questions/2340020/… 但它似乎不适合您。虽然我也不喜欢两个查询选项,但它是最干净的方式(没有嵌入 if 语句)。当然请注意,您希望在事务中执行此操作,以免出现竞争条件。【参考方案3】:

您需要的是 SQL Server 2008 'MERGE' 命令。这是 MS 文档页面http://technet.microsoft.com/en-us/library/bb510625.aspx。

片段:

MERGE INTO dbo.myTable AS Target
USING (VALUES   ('something 1','other 1'), 
                ('something 2', 'other 2'), 
                ('something 3', 'other 3'))
       AS Source (Field1, Field2)
ON Target.myId = Source.myId
WHEN MATCHED THEN
    UPDATE SET Field1 = Source.Field1,
               Field2 = Source.Field2
WHEN NOT MATCHED BY TARGET THEN
    INSERT (Field1, Field2) 
    VALUES (Field1, Field2)

我从 SQL2005 标记中猜测这对您没有多大帮助(对不起!),所以 casperOne 的答案可能是最合适的。

【讨论】:

@MPritch:不幸的是,他使用的是 SQL Server 2005,如标签所示。 谢谢。我在我的回答中做了这个观察,并推荐了你对 SQL 2005 的回答(以及支持你的回答......)。我的答案是为可能正在使用 SQL 2008 的社区添加的 @casperOne - 我想这是你的反对意见。没有根据的恕我直言。 *** 是一种长期资源,因此虽然这个答案对 OP 没有直接用处,正如 MPritch 所观察到的,但人们在未来数月和数年内谷歌搜索可能会发现它很有用。 +1 我来反驳。 @David M:恕我直言,您的意见与 SO 的实践背道而驰,正如 Meta SO 上关于 downvoting 的讨论所指出的那样:meta.stackexchange.com/questions/2451/… - 具体而言,上下文的答案是错误的提出问题。如果是 SQL Server 2005,则不会投反对票,但话又说回来,不会发布答案。 @David M:此外,在对答案进行编辑之前无法更改投票,因此即使进一步澄清,我也无法删除反对票。另外,当您将鼠标悬停在赞成箭头上时,请注意工具提示,它显示“这个答案很有用”。您投票赞成的理由无视这一点,并且您将其用作报复的工具,这对任何人都没有好处,并且在技术上是对投票系统的滥用。

以上是关于在 SQL Server 2005 的查询中与 T-SQL 进行数据比较的主要内容,如果未能解决你的问题,请参考以下文章

SQL 按问题分组 SQL Server 2005 CE

对表使用 sql server 2005 同义词会导致动态查询生成错误

如何在 SQL Server 2005 中回滚 UPDATE 查询?

如何在 SQL Server 2005/2008 中清除查询执行统计信息

如何在SQL Server 2005中回滚UPDATE查询?

SQL Server 2005 查询优化