2010-08-05 97 views
3

我在SQL Server存儲過程中遇到了一個非常奇怪的問題。SQL存儲過程問題 - 十進制值轉換問題

我有兩個數據庫。其中一個包含我的結算系統的數據庫。另一種是彙總數據的報告系統。在這個數據庫中有一張帶有總結工作信息的表格。創建此數據時,其中一個字段BilledToDate爲空。我編寫了一個存儲過程,創建一個通過該表的光標並獲取所有作業編號。然後,我查看每個工作號碼並針對帳單數據庫運行查詢,以獲取針對工作收取的總計費用。一旦我有這個總數,我用這個值更新BilledToDate列。

問題是,運行存儲過程後,一些結果是正確的,有些不是。似乎沒有任何合理的解釋,爲什麼一個是正確的,下一個是不正確的。我在存儲過程中放置​​了一些打印語句,並且所有的值都是正確的。例如,對於一條記錄,正確的總和爲99,218.25,但更新會將BillingToDate字段中的值設置爲14,700.70。我在表中添加了一個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 

任何想法,將不勝感激。

謝謝。

約翰

+0

您能否提供SP工作的表結構?另外,你是否嘗試過暴露問題的小型數據集?你能提供一些樣本數據嗎? – bobs 2010-08-05 21:21:18

+0

爲什麼BilledToDate使用錢的數據類型: SELECT @BilledToDate = CONVERT(錢,CASE WHEN SUM(invoiceamt)> 0 THEN SUM(InvoiceAmt)ELSE 0 END) 時,它的initally定義爲一個十進制(16,2) ? 爲什麼billedtoDATE被分配一個十進制值? – 2010-08-05 21:24:51

+0

我認爲他的意思是BilledToDate是「您迄今爲止收到了多少錢(即」迄今爲止「)」。 – dave 2010-08-05 21:36:07

回答

2

我注意到你可能會看到的一些東西。順便說一句 - 你真的在想這個 - 關於這方面的一些想法。


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 
+0

我從來沒有見過你的建議,所以我想這個工作。當我執行這個語句時,我得到一個「無效的列名shortchar01'」錯誤。 我看過查詢,我不知道爲什麼它不識別I.shortchar01。 任何想法? – user412421 2010-08-05 23:25:49

+0

你有兩個'SELECT @ BilledToDate'版本是不一樣的。首先是檢查底片。 – 2010-08-06 00:17:48

+0

感謝@Martin。是的 - 你是對的 - 我的錯誤。如果@ user412421只想總結正面的發票(而不是什麼 - 退款等),那麼他們需要使用第一張。 – dave 2010-08-06 01:52:16

0

這是做你正在做的事嗎?

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) 
+0

這工作!感謝您花時間回覆此問題。 – user412421 2010-08-06 00:49:53