每个备选方案的 T-SQL?
Posted
技术标签:
【中文标题】每个备选方案的 T-SQL?【英文标题】:T-SQL For Each Alternative? 【发布时间】:2010-06-08 22:32:14 【问题描述】:我需要从一个表中获取数据并将其导入到另一个表中。在伪代码中是这样的:
For Each row in table1
If row.personid is in table2 then
update table2.row
Else
insert row into table2
End If
Next
在 T-SQL 中执行此操作的最佳方法是什么?据我了解,T-SQL 不支持 For Each..Next,那么我有什么替代方案?
【问题讨论】:
表一是不是每个personid都有一行,还是同一个person id可以有多行? 【参考方案1】:如果您使用的是 SQL Server 2008,那么您可以使用 MERGE
语句。也许是这样的:
MERGE table2 AS t -- target
USING table1 AS s -- source
ON ( t.personid = s.personid )
WHEN MATCHED THEN
UPDATE
SET second_column = s.second_column,
third_column = s.third_column,
etc = s.etc
WHEN NOT MATCHED THEN
INSERT ( personid, second_column, third_column, etc )
VALUES ( s.personid, s.second_column, s.third_column, s.etc )
【讨论】:
【参考方案2】:在所有条件相同的情况下,基于集合的操作更好。
update t1
set t1.x = t2.x
.
.
.
from table1 t1
inner join table2 t2 on t1.id = t2.t1id
then
insert into table1
select * from table2 t2 where t2.t1id not in (select table1.id from table1 )
【讨论】:
@jvilalta 你是说数据集越大越有理由遍历每条记录?我不得不不同意。 并不是说有更多的原因,只是在一个语句中进行插入和更新会将这一切都放在一个事务中,如果数据集足够大,那么事务可能会失败或者它将运行一段时间很长的时间,阻止其他事务完成。 @jvilalta 我很确定它不会像循环遍历每条记录那样长时间运行或占用尽可能多的资源。 实际上应该与其他阅读器同时运行良好,至少在快照隔离模式下? @TskTsk 如果是这种情况,您可以对表上的键子集执行基于集合的查询。即 personid 0 到 500000 和 500001-1000000 等...它仍然比一个快... ) 也是这样。通常数据库具有与数据访问相关的一定开销,因此通过一次访问一个事物,您为每条记录支付开销,而基于集合的事物为集合中的所有记录获得一次开销......【参考方案3】:您可以像其他人所描述的那样使用光标。就我个人而言,我喜欢像这样连续执行两个语句:
UPDATE tbl2 SET field1=tbl1.field1, field2=tbl1.field2 -- etc.
FROM tb12
JOIN tbl1 on tbl2.personid = tbl1.personid
INSERT tbl2 (personid, field1, field2)
SELECT personid, field1, field2
FROM tbl1
WHERE NOT EXISTS (select personid from tbl2 where personid = tbl1.persondid)
【讨论】:
【参考方案4】:在 while 循环中这样做是错误的。 对于您的情况,您可以在 sql server 2008 中使用新的 MERGE 语句。 这是simple example 说明如何操作。
【讨论】:
【参考方案5】:如果您使用的是 SQL Server 2008,那么最好的方法是使用 MERGE
语句。比如……
MERGE INTO target_table t
USING source_table s
ON t.personid = s.personid
WHEN MATCHED THEN
UPDATE ...
WHEN NOT MATCHED THEN
INSERT ...
【讨论】:
【参考方案6】:您声明了 TSQL,但没有给出版本。如果您使用的是 SQL2008,Merge 语句应该可以满足您的需求。
【讨论】:
谢谢,抱歉,我们使用 SQL 2008,但我们的一些数据库在 SQL 2005/2000 兼容模式下运行(第三方旧版软件) 它可能仍然有效。你试过了吗?编辑:这里说它支持 SQL 2005 兼容模式,但对 2000 问题保持沉默! msdn.microsoft.com/en-us/library/bb510680.aspx【参考方案7】:最常见的方法之一是使用游标。这样,您可以通过 UPDATE 或 INSERT 遍历查询返回的每条记录并相应地处理它。
见:http://msdn.microsoft.com/en-us/library/ms180169.aspx
【讨论】:
谢谢。我认为这是一个选项 - 但也读到这违反了最佳实践 b/c 游标在内存管理等方面无效? @davemackey 你没看错。我不敢相信有 2 个人为此建议了光标! 别射信使,马丁。光标是对给定伪代码的合理响应,并且在不知道更多信息的情况下,可能是一个完美的解决方案。这取决于它的使用方式、表格大小等。 当存在明显的基于集合的解决方案时,我默认不使用它们。关于这个问题的有趣线程。 ***.com/questions/24168/…以上是关于每个备选方案的 T-SQL?的主要内容,如果未能解决你的问题,请参考以下文章