SQL存储过程问题-十进制值转换问题

SQL存储过程问题-十进制值转换问题,sql,sql-server,Sql,Sql Server,我在SQL Server存储过程中遇到了一个非常奇怪的问题 我有两个数据库。其中一个包含我的计费系统的数据库。另一个是具有汇总数据的报告系统。在这个数据库中有一个包含汇总作业信息的表。创建此数据时,其中一个字段BilledToDate为空。我编写了一个存储过程,它创建了一个游标,该游标遍历该表并获取所有作业编号。然后,我检查每个作业编号,并对账单数据库运行查询,以获得已针对作业收取的账单总额。一旦我有了这个总数,我就用这个值更新BilledToDate列 问题是,在运行存储过程之后,有些结果是正

我在SQL Server存储过程中遇到了一个非常奇怪的问题

我有两个数据库。其中一个包含我的计费系统的数据库。另一个是具有汇总数据的报告系统。在这个数据库中有一个包含汇总作业信息的表。创建此数据时,其中一个字段BilledToDate为空。我编写了一个存储过程,它创建了一个游标,该游标遍历该表并获取所有作业编号。然后,我检查每个作业编号,并对账单数据库运行查询,以获得已针对作业收取的账单总额。一旦我有了这个总数,我就用这个值更新BilledToDate列

问题是,在运行存储过程之后,有些结果是正确的,有些则不是。对于为什么一个是正确的,而下一个是错误的,似乎没有任何合乎逻辑的解释。我在存储过程中放入了一些print语句,所有的值都是正确的。例如,对于一条记录,正确的总和为99218.25,但更新将值14700.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, SUM(ISNULL(invoiceamt,0)))
*注意在这两种情况下都使用ISNULL(),这一点很重要,因为不能对null进行数学运算


不需要使用光标。只需在一个update语句中将两个表连接在一起,并将其作为一个批处理

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

这和你想做的一样吗

WITH inv AS
(
SELECT shortchar01, 
CONVERT(MONEY, CASE WHEN SUM(invoiceamt) > 0 THEN 
                                             SUM(InvoiceAmt) 
                                             ELSE 0 END) AS BilledToDate
FROM mfgsys803.dbo.invchead
GROUP BY shortchar01
)
 UPDATE StructuralOpenBilling
 SET BilledToDate = inv.BilledToDate, 
     BilledCheck = CONVERT(VARCHAR(50), inv.BilledToDate)
FROM StructuralOpenBilling sob
JOIN inv ON inv.shortchar01 = RTRIM(sob.JobID)

您能否提供SP使用的表结构?另外,您是否尝试过更小的数据集来暴露问题?您能提供一些示例数据吗?为什么BilledToDate使用货币数据类型:选择@BilledToDate=CONVERT(money,当SUM(invoiceamt)>0时为CASE,然后选择SUM(invoiceamt)或0 END,当它最初定义为十进制(16,2)时?为什么给billedtoDATE分配一个十进制值呢?我想他的意思是“billedtoDATE是指“到目前为止,您已经收到多少账单了”(即“到目前为止”)。我从来没有看到您的建议,所以我想让它起作用。执行此语句时,会出现“无效列名'shortchar01'”错误。我查看了查询,不知道为什么它不识别I.shortchar01。有什么想法吗?你的两个
SELECT@biledtodate
版本不一样。首先是检查底片。谢谢@Martin。是的,你是对的,我错了。如果@user412421只想对正发票求和(与之相反——退款等),那么他们需要使用第一个。@user412421——我修正了它——对此表示抱歉。
WITH inv AS
(
SELECT shortchar01, 
CONVERT(MONEY, CASE WHEN SUM(invoiceamt) > 0 THEN 
                                             SUM(InvoiceAmt) 
                                             ELSE 0 END) AS BilledToDate
FROM mfgsys803.dbo.invchead
GROUP BY shortchar01
)
 UPDATE StructuralOpenBilling
 SET BilledToDate = inv.BilledToDate, 
     BilledCheck = CONVERT(VARCHAR(50), inv.BilledToDate)
FROM StructuralOpenBilling sob
JOIN inv ON inv.shortchar01 = RTRIM(sob.JobID)