我在SAM_Updates表中有以下信息
37-529-1 1
13793-1 1
42086-1 1
13793-1 1
我正在运行此查询以更新自定义标签匹配的另一个表(部件)中的数量值。
update Parts
set Parts.Quantity = cast(cast(Parts.quantity as int) -
cast(SAMS_Updates.quantity as int) as varchar(100))
from SAMS_Updates
where Parts.SAMS_Custom_Label = SAMS_Updates.Custom_Label
我遇到的问题是值13793.它只是更新从数量中减去一个。我希望它最终减去两个,因为有两个单独的行。
知道为什么会这样吗?我正在使用SQL Server Express。
答案 0 :(得分:3)
您可以使用联接到聚合Quantity
中SAM_Updates
的子查询:
update p
set p.Quantity = p.Quantity - su.Quantity
from parts p
inner join (
select Custom_Label, sum(cast(Quantity as int)) as Quantity
from SAMS_Updates
group by Custom_Label
) su
on p.SAMS_Custom_Label = su.Custom_Label
rextester演示:http://rextester.com/RTUE81736
假设每个部分在更新之前有10 Quantity
,则返回:
+-------------------+----------+
| SAMS_Custom_Label | Quantity |
+-------------------+----------+
| 37-529-1 | 9 |
| 13793-1 | 8 |
| 42086-1 | 9 |
+-------------------+----------+
答案 1 :(得分:0)
这是在基于集合的解决方案上建议使用迭代解决方案的特殊情况之一。这意味着利用(大多数情况下不建议使用)游标操作来一次应用一行修改。基于集合的数据修改方法将在不同的阶段执行,并且直到语句集执行完成后整个集合完成更新之后,才能引用记录的新预期值。
虽然包含对每个零件分组的汇总数量的子查询将实现对零件库存数量进行修改的基本任务,但它不能确保每个数据驱动的更新均已完成且不会在随后执行的零件库存更新过程中重新应用。
但是,请注意,使用游标可能需要其他注意事项,以适当地调整查询,以减轻因其相关的较高开销而对性能造成的潜在影响。
以下代码概述了如何使用SQL游标多次更新同一行:
/*Create Base Tables*/
/*Parts Table*/
/*Create Table*/
drop table if exists #parts
create table #parts
(idParts bigint identity(1, 1) not null,
SAMS_Custom_Label varchar(25) primary key not null,
Quantity int not null default 0 check(Quantity >= 0)) --check assumes backorder logic is separate
/*Insert Values*/
insert into #parts
(SAMS_Custom_Label,
Quantity)
values ('37-529-1', 5),
('13793-1', 5),
('42086-1', 5)
/*Review Current Parts Quantities*/
select P.SAMS_Custom_Label,
P.Quantity
from #parts P
/*SAM_Updates Table*/
/*Create Table*/
drop table if exists #SAM_Updates
create table #SAM_Updates
(idSAM_Updates bigint identity(1, 1) primary key not null,
Custom_Label varchar(25) not null, --the #parts table should be reference for referential integrity
Quantity int not null check(Quantity <> 0),
partsQuantityUpdated bit not null default 'false') --Indicates Quantity Update was applied to #parts table
/*Insert Values*/
insert into #SAM_Updates
(Custom_Label,
Quantity)
values ('37-529-1', 1),
('13793-1', 1),
('42086-1', 1),
('13793-1', 1)
/*Parts Inventory Update Process*/
/*Setup Cursor*/
/*Operational parms*/
declare @idSAM_Updates bigint,
@Custom_Label varchar(25),
@Quantity int
/*Create & Open Cursor record set*/
DECLARE C CURSOR
FOR ( select SU.idSAM_Updates,
SU.Custom_Label,
SU.Quantity
from #SAM_Updates SU
where SU.partsQuantityUpdated = 'false') --Apply only updates that haven't been performed
OPEN C
/*Initiate first fetch record*/
FETCH NEXT
FROM C
INTO @idSAM_Updates,
@Custom_Label,
@Quantity
/*Perform Loop*/
WHILE @@FETCH_STATUS = 0
BEGIN
/*Apply difference to Parts Inventory Quantity*/
update P
set P.Quantity = P.Quantity - @Quantity
from #parts P
where P.SAMS_Custom_Label = @Custom_Label
/*Mark current SAM_Updates record as applied to #parts table*/
update SU
set SU.partsQuantityUpdated = 'true'
from #SAM_Updates SU
where SU.idSAM_Updates = @idSAM_Updates
/*Initiate next fetch record*/
FETCH NEXT
FROM C
INTO @idSAM_Updates,
@Custom_Label,
@Quantity
END
/*Close Cursor*/
CLOSE C
DEALLOCATE C
/*Examine Results*/
/*Updated Parts Quantities*/
select P.SAMS_Custom_Label,
P.Quantity
from #parts P
/*new records added to the #SAM_Updates table will be applied to the parts inventory each time the Parts Inventory Update Process is reran*/