我在SQL Server存储过程中遇到了一个非常奇怪的问题.
我有两个数据库.一个包含我的计费系统的数据库.另一种是具有汇总数据的报告系统.在此数据库中,有一个包含汇总作业信息的表.创建此数据时,其中一个字段BilledToDate为null.我编写了一个存储过程,创建一个遍历此表的游标并获取所有作业号.然后,我查看每个工作号码并对计费数据库运行查询,以获得已根据工作收取的计费总额.获得此总数后,我将使用此值更新BilledToDate列.
问题是在运行存储过程后,某些结果是正确的,而有些则不是.似乎没有任何合理的解释为什么一个是正确的而下一个是不对的.我在存储过程中放了一些print语句,所有值都是正确的.例如,对于一条记录,正确的总和为99,218.25,但更新将值14,700.70放入BilledToDate字段.我在表中添加了一个varchar列并填充了该字段.他们都是正确的.这让我相信它是一个投射问题,但我检查并仔细检查了我的数据类型,它们看起来都是正确的.我正在把头发拉出来(剩下的东西).
我的存储过程如下. InvoiceAmt字段是invchead表中的十进制(16,2),我在整个过程中保持一致,所以我不承认为什么会发生这种情况.
ALTER PROCEDURE [dbo].[sp_CalculateBilledToDate]
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @JobID varchar(10)
DECLARE @RecordID int
DECLARE @BilledToDate decimal(16,2)
DECLARE c1 CURSOR FOR
SELECT JobID, RecordID
FROM StructuralOpenBilling
OPEN c1
FETCH NEXT FROM c1
INTO @JobID, @RecordID
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @BilledToDate = CONVERT(money, CASE WHEN SUM(invoiceamt) > 0 THEN SUM(InvoiceAmt) ELSE 0 END)
FROM mfgsys803.dbo.invchead
WHERE shortchar01 = RTRIM(@JobID)
PRINT 'Record ID: ' + CONVERT(varchar(10), @RecordID) + ' JobID: ' + RTRIM(CONVERT(varchar(10), @JobID)) + ' Billed: ' + CONVERT(varchar(10), @BilledToDate)
UPDATE StructuralOpenBilling
SET BilledToDate = @BilledToDate, BilledCheck = CONVERT(varchar(50), @BilledToDate)
WHERE RecordID = @RecordID
PRINT 'Record ID: ' + CONVERT(varchar(10), @RecordID) + ' JobID: ' + RTRIM(CONVERT(varchar(10), @JobID)) + ' Billed: ' + CONVERT(varchar(10), @BilledToDate)
FETCH NEXT FROM c1
INTO @JobID, @RecordID
END
CLOSE c1
DEALLOCATE c1
END
任何想法,将不胜感激.
谢谢.
约翰
最佳答案 我注意到你可能会看到的一些事情.顺便说一句 – 你真的过分思考了这一点 – 这里也有一些想法.
SELECT @BilledToDate = CONVERT(money, CASE WHEN SUM(ISNULL(invoiceamt,0)) > 0 THEN SUM(ISNULL(InvoiceAmt,0)) ELSE 0 END)
是相同的
SELECT @BilledToDate = CONVERT(money, SUM(ISNULL(invoiceamt,0)))
*注意在两者中使用ISNULL() – 这很重要,因为你不能对空值进行数学运算.
没必要使用游标.只需在一个更新语句中将两个表连接在一起,即可批量处理.
UPDATE StructuralOpenBilling
SET S.BilledToDate = I.BilledToDate
FROM
StructuralOpenBilling S
INNER JOIN
(SELECT shortchar01, CONVERT(money, SUM(ISNULL(invoiceamt,0))) as BilledToDate
FROM mfgsys803.dbo.invchead) I
ON
S.JobID = I.shortchar01