使用游标基于子查询更新数据库的替代方法
Alternatives to using cursor for updating a database based on a subquery
也许这个标题并不是很有启发性,但我不能想出一个不那么做作的标题。这是我的问题:
我正在使用 table 的数据看起来像
id cId ver active
1 100 1 0
2 100 2 1
3 100 3 1
4 200 1 0
5 200 2 1
6 300 1 1
对于此table,Id 是主键,cId 标识客户端。基本上我们正在存储版本控制历史。
我试图解决的问题是更新数据库以仅对最新版本设置 active =1,这是每个客户端的最高 [ver]。 (cId 为 100 的客户端在示例中被窃听)
现在,我已经设法编写了以下查询,为我提供了可以处理的数据
select t.id, t.cId,t.version
from (select *
from comp.Clients a
where a.ver = (select max(b.ver) from comp.Clients b where a.cId=b.cIdentifier)
) t
从那时起,我的解决方案是将该查询插入游标,对于游标上的每条记录,我会将当前记录的 table 更新为 active=0 和 active =1。
问题是游标就是它们的本质,有没有什么东西可以让我在这里有不错的表现?我不擅长 CTE,所以我无法提出围绕它的解决方案。实际 table 有大约 10k 条记录和大约 50 个字段。
您应该为每个 CId
找到最后一个 ver
,然后更新您的 table
select cId,Max(ver) as MaxVer into #tmpTable from comp.Clients group by cid
update c
set active = case when t.cId is not null then 1 else 0 end
from comp.Clients c left join #tmpTable t on t.CId=c.CId and t.MaxVer=c.ver
不使用游标,而是使用 2 个更新。一个将值更新为 0,另一个将客户端 ID 的最新版本设置为 1。这应该足够了。
使用可更新的 CTE:
with toupdate as (
select c.*,
max(ver) over (partition by CId) as max_ver
from comp.Clients c
)
update toupdate
set active = (case when max_ver = ver then 1 else 0 end);
您可以添加一个 where
子句来限制要更新的行数,如果您愿意的话:
where active <> (case when max_ver = ver then 1 else 0 end)
也许这个标题并不是很有启发性,但我不能想出一个不那么做作的标题。这是我的问题:
我正在使用 table 的数据看起来像
id cId ver active
1 100 1 0
2 100 2 1
3 100 3 1
4 200 1 0
5 200 2 1
6 300 1 1
对于此table,Id 是主键,cId 标识客户端。基本上我们正在存储版本控制历史。
我试图解决的问题是更新数据库以仅对最新版本设置 active =1,这是每个客户端的最高 [ver]。 (cId 为 100 的客户端在示例中被窃听)
现在,我已经设法编写了以下查询,为我提供了可以处理的数据
select t.id, t.cId,t.version
from (select *
from comp.Clients a
where a.ver = (select max(b.ver) from comp.Clients b where a.cId=b.cIdentifier)
) t
从那时起,我的解决方案是将该查询插入游标,对于游标上的每条记录,我会将当前记录的 table 更新为 active=0 和 active =1。
问题是游标就是它们的本质,有没有什么东西可以让我在这里有不错的表现?我不擅长 CTE,所以我无法提出围绕它的解决方案。实际 table 有大约 10k 条记录和大约 50 个字段。
您应该为每个 CId
找到最后一个 ver
,然后更新您的 table
select cId,Max(ver) as MaxVer into #tmpTable from comp.Clients group by cid
update c
set active = case when t.cId is not null then 1 else 0 end
from comp.Clients c left join #tmpTable t on t.CId=c.CId and t.MaxVer=c.ver
不使用游标,而是使用 2 个更新。一个将值更新为 0,另一个将客户端 ID 的最新版本设置为 1。这应该足够了。
使用可更新的 CTE:
with toupdate as (
select c.*,
max(ver) over (partition by CId) as max_ver
from comp.Clients c
)
update toupdate
set active = (case when max_ver = ver then 1 else 0 end);
您可以添加一个 where
子句来限制要更新的行数,如果您愿意的话:
where active <> (case when max_ver = ver then 1 else 0 end)