2010-08-05 3 views
3

У меня возникла очень странная проблема в хранимой процедуре SQL Server.Проблема с сохраненной процедурой SQL - проблема с преобразованием десятичного значения

У меня есть две базы данных. Один содержит базу данных для моей биллинговой системы. Другая - система отчетности с обобщенными данными. Внутри этой базы данных есть таблица с обобщенной информацией о задании. Когда эти данные создаются, одно из полей BilledToDate равно null. Я написал хранимую процедуру, которая создает курсор, который проходит через эту таблицу и получает все номера заданий. Затем я просматриваю каждый номер задания и запускаю запрос к базе данных фактурирования, чтобы получить общую сумму выставления счетов, взимаемую с работы. Как только я получу эту сумму, я обновляю столбец BilledToDate с этим значением.

Проблема в том, что после запуска хранимой процедуры некоторые из результатов являются правильными, а некоторые нет. Кажется, нет логического объяснения, почему кто-то прав, а следующий - нет. Я поместил некоторые операторы печати в хранимую процедуру, и все значения были правильными. Например, для одной записи правильная сумма составила 99 218,25, но обновление добавило значение 14 700,00 в поле BilledToDate. Я добавил столбец varchar в таблицу и заполнил это поле. Они все правильные. Это заставляет меня думать, что это проблема кастинга, но я проверил и дважды проверял свои типы данных, и все они выглядят правильно. Я вытягиваю свои волосы на этом (что мало осталось).

Моя хранимая процедура ниже. Поле InvoiceAmt является десятичным (16,2) в таблице invchead, и я сохранил его на протяжении всего процесса, поэтому я не понимаю, почему это происходит.

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 

Любые идеи были бы оценены.

Спасибо.

John

+0

Можете ли вы предоставить структуры таблиц, с которыми работает SP? Кроме того, вы пробовали меньший набор данных, который выявляет проблему? Можете ли вы предоставить некоторые примеры данных? – bobs

+0

Почему BilledToDate используя деньги типа данных: ВЫБРАТЬ @BilledToDate = CONVERT (деньги, случай, когда SUM (invoiceamt)> 0 THEN SUM (InvoiceAmt) ELSE 0 END) , когда он Initally определен как десятичную (16,2) ? И почему присвоено значение bitedtoDATE десятичное значение? –

+0

Я думаю, что он означает BilledToDate, чтобы быть «Сколько денег вы были выставлены на сегодняшний день (т. Е.« До сих пор »)». – dave

ответ

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

+0

Две версии 'SELECT @ BilledToDate', которые у вас есть, не совпадают. Первая делает проверку на негативы. –

+0

Спасибо @Martin. Да, вы правы - моя ошибка. Если @ user412421 хочет только суммировать положительные счета-фактуры (в отличие от того, что - возврат и т. Д.?), Тогда им нужно будет использовать первый. – dave

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

Смежные вопросы