我有以下查询,它根据采购订单检查收货,以查看最初订购的商品以及通过收货预订的商品数量.例如,我下了10个香蕉奶昔的采购订单,然后我生成了一个收据,说明我在所述采购订单上收到了5个这样的奶昔.
SELECT t.PONUM, t.ITMNUM, t.ordered,
SUM(t.received) as received,
t.ordered - ISNULL(SUM(t.received),0) as remaining,
SUM(t.orderedcartons) as orderedcartons,
SUM(t.cartonsreceived) as cartonsreceived,
SUM(t.remainingcartons) as remainingcartonsFROM(SELECT pod.PONUM,
pod.ITMNUM, pod.QTY as ordered, ISNULL(grd.QTYRECEIVED, 0) as received,
pod.DELIVERYSIZE as orderedcartons,
ISNULL(grd.DELIVERYSIZERECEIVED, 0) as cartonsreceived,
(pod.DELIVERYSIZE - ISNULL(grd.DELIVERYSIZERECEIVED, 0)) as remainingcartons
FROM TBLPODETAILS pod
LEFT OUTER JOIN TBLGRDETAILS grd
ON pod.PONUM = grd.PONUM and pod.ITMNUM = grd.ITMNUM) t
GROUP BY t.ITMNUM, t.PONUM, t.ordered
ORDER BY t.PONUM
Run Code Online (Sandbox Code Playgroud)
返回以下数据:
PONUM ITMNUM ordered received remaining orderedcartons cartonsreceived remainingcartons
1 1 5.0000 3.0000 2.0000 5.0000 3.0000 2.0000
Run Code Online (Sandbox Code Playgroud)
接下来我有一个C#循环来根据我从上面的查询中获得的数据生成更新查询:
foreach (DataRow POUpdate in dt.Rows) {...
query += "UPDATE MYTABLE SET REMAININGITEMS=" + remainingQty.ToString()
+ ", REMAININGDELIVERYSIZE=" + remainingBoxes.ToString() + " WHERE ITMNUM="
+ itemNumber + " AND PONUM=" + poNumber + ";";
Run Code Online (Sandbox Code Playgroud)
然后,我对DB执行每个更新查询.哪个在我的本地开发机器上工作正常.
但是,部署到生产服务器会在第一次查询时回收超过150,000条记录.
所以循环这么多行会锁定SQL和我的应用程序.是foreach吗?是原始选择将所有数据加载到内存中吗?都?我可以将此查询转换为单个查询并删除C#循环吗?如果是这样,最有效的方法是什么?
在SQL中,目标应该是立即在整个表上编写操作.这样做SQL服务器非常有效,但是在任何交互上都需要很大的开销,因为它需要处理事务的一致性,原子性等等.所以在某种程度上,每个事务的固定成本很高,因为服务器做它的事情,但是事务中额外行的边际成本非常低 - 更新1m行可能比更新10行快1/2.
这意味着foreach将导致SQL服务器不断地与您的应用程序来回,并且每次都会发生锁定/解锁和执行事务的固定成本.
你能编写查询来在SQL中运行,而不是在C#中操作数据吗?看来你想根据你的select语句编写一个相对简单的更新(例如,根据ID匹配,参见从一个表到另一个表的SQL更新.
尝试类似下面的内容(未经过代码测试,因为我无法访问您的数据库结构等):
UPDATE MYTABLE
SET REMAININGITEMS = remainingQty,
REMAININGDELIVERYSIZE=remainingBoxes
From
(SELECT t.PONUM, t.ITMNUM, t.ordered,
SUM(t.received) as received,
t.ordered - ISNULL(SUM(t.received),0) as remaining,
SUM(t.orderedcartons) as orderedcartons,
SUM(t.cartonsreceived) as cartonsreceived,
SUM(t.remainingcartons) as remainingcartonsFROM(SELECT pod.PONUM,
pod.ITMNUM, pod.QTY as ordered, ISNULL(grd.QTYRECEIVED, 0) as received,
pod.DELIVERYSIZE as orderedcartons,
ISNULL(grd.DELIVERYSIZERECEIVED, 0) as cartonsreceived,
(pod.DELIVERYSIZE - ISNULL(grd.DELIVERYSIZERECEIVED, 0)) as remainingcartons
FROM TBLPODETAILS pod
LEFT OUTER JOIN TBLGRDETAILS grd
ON pod.PONUM = grd.PONUM and pod.ITMNUM = grd.ITMNUM) t
GROUP BY t.ITMNUM, t.PONUM, t.ordered
ORDER BY t.PONUM ) as x
join MYTABLE on MYTABLE.ITMNUM=x.itmnum AND MYTABLE.PONUM=i.ponum
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
286 次 |
| 最近记录: |