2016-11-20 7 views
1

Я продолжаю получать эту ошибку, когда запускаю простой оператор обновления.Ошибка конверсии в курсоре?

Msg 16922, Level 16, State 1, Procedure TRG_MEM_BALANCE_AWW, Line 72
Cursor Fetch: Implicit conversion from data type datetime to decimal is not allowed.

Это мой код, который у меня есть для запуска. Я не вижу, что неправильно преобразуется?

ALTER TRIGGER [dbo].[TRG_MEM_BALANCE_AWW] 
ON [dbo].[DETAILRENTAL] 
AFTER INSERT, DELETE, UPDATE 
AS 
BEGIN 
    IF(EXISTS(SELECT * FROM inserted) 
     AND 
     EXISTS(SELECT * FROM deleted)) 
    BEGIN 
     DECLARE CURSORFORUPDATE CURSOR FOR 
      SELECT 
       I.RENT_NUM, I.DETAIL_DUEDATE, I.DETAIL_RETURNDATE, 
       I.DETAIL_DAILYLATEFEE, D.DETAIL_DUEDATE, 
       D.DETAIL_RETURNDATE, D.DETAIL_DAILYLATEFEE 
      FROM 
       inserted I 
      INNER JOIN 
       DELETED D ON I.Rent_Num = D.Rent_Num 
          AND I.Vid_Num = D.Vid_Num 

     DECLARE @RENT_NUM INT 
     DECLARE @RETURN_DATE_NEW DATETIME 
     DECLARE @DUE_DATE_OLD DATETIME 
     DECLARE @DUE_DATE_NEW DATETIME 
     DECLARE @RETURN_DATE_OLD DATETIME 
     DECLARE @DAILY_LATE_FEE_NEW DECIMAL(5,2) 
     DECLARE @DAILY_LATE_FEE_OLD DECIMAL(5,2) 
     DECLARE @LATE_FEE_PRIOR DECIMAL(5,2) 
     DECLARE @LATE_FEE_AFTER DECIMAL(5,2) 
     DECLARE @CHANGE DECIMAL (5,2) 

     OPEN CURSORFORUPDATE 

     FETCH NEXT FROM CURSORFORUPDATE INTO @RENT_NUM, @DUE_DATE_NEW, @RETURN_DATE_NEW, @DAILY_LATE_FEE_NEW, @DUE_DATE_OLD, @RETURN_DATE_OLD, @DAILY_LATE_FEE_OLD 

     WHILE (@@FETCH_STATUS = 0) 
     BEGIN 

--A 
IF(@RETURN_DATE_OLD > @DUE_DATE_OLD) 

BEGIN 

    SELECT @LATE_FEE_PRIOR = DATEDIFF(DAY, @DUE_DATE_OLD, @RETURN_DATE_OLD) * @DAILY_LATE_FEE_OLD 

    END 
    ELSE 
     SELECT @LATE_FEE_PRIOR = 0 
--B 
    IF(@RETURN_DATE_NEW > @DUE_DATE_NEW) 
    BEGIN 
    SELECT @LATE_FEE_AFTER = DATEDIFF(DAY, @DUE_DATE_NEW, @RETURN_DATE_NEW) * @DAILY_LATE_FEE_NEW 

    END 
    ELSE 
     SELECT @LATE_FEE_AFTER = 0 

--C 
    SELECT @CHANGE = @LATE_FEE_AFTER - @LATE_FEE_PRIOR 

--D 
    IF(@CHANGE <> 0) 
    BEGIN 
    DECLARE @MEM_NUM INT 
    SELECT @MEM_NUM = M.Mem_Num 
    FROM RENTAL R INNER JOIN MEMBERSHIP M ON R.MEM_NUM = M.MEM_NUM AND R.RENT_NUM = @RENT_NUM 

    UPDATE MEMBERSHIP 
    SET Mem_Balance = MEM_BALANCE + @CHANGE 
    WHERE Mem_Num = @MEM_NUM 

    FETCH NEXT FROM CURSORFORUPDATE 
    INTO @RENT_NUM, @DUE_DATE_NEW, @DUE_DATE_OLD, @RETURN_DATE_NEW, @RETURN_DATE_OLD, @DAILY_LATE_FEE_NEW, @DAILY_LATE_FEE_OLD 

    END 
    CLOSE CURSORFORUPDATE 
    DEALLOCATE CURSORFORUPDATE 

    END 
END 
END 

Обновление Я бегущая является

UPDATE DETAILRENTAL 
SET DETAIL_RETURNDATE = 2013-03-10 
WHERE RENT_NUM = 1001 

Это делает его так, что фильм возвращается в конце таблицы DETAILRENTAL, который должен обновлять баланс члена в таблице ЧЛЕНСТВО. Будем очень благодарны за любые идеи о том, как исправить эту ошибку.

+0

Я добавил тег базы данных. Синтаксис - это, очевидно, SQL Server. –

ответ

0

Поле DETAIL_RETURNDATE имеет datetime или date типа, вероятно, пока вы пытаетесь установить его на номер: 2013-03-10 = 2013 минус 3 минус 10 = 2000

Попробуйте это:

Update DETAILRENTAL 
    Set DETAIL_RETURNDATE = Convert(datetime, '2013-03-10', 23) 
    Where RENT_NUM = 1000; 

В этом случае Convert(datetime, , 23) может не быть строго необходимым, но является хорошей практикой, если ваши входные даты соответствуют согласованному формату.

Редактировать

Первое может быть источником проблем, но я также заметил, что более вероятно, что вызывает ошибку

ALTER TRIGGER [dbo].[TRG_MEM_BALANCE_AWW] 
ON [dbo].[DETAILRENTAL] 
AFTER INSERT, DELETE, UPDATE 
AS 
BEGIN 
    IF (EXISTS (SELECT * FROM inserted) AND EXISTS (SELECT * FROM deleted)) 
    BEGIN 
     DECLARE CURSORFORUPDATE CURSOR FOR 
     SELECT I.RENT_NUM, I.DETAIL_DUEDATE, I.DETAIL_RETURNDATE,I.DETAIL_DAILYLATEFEE, 
      D.DETAIL_DUEDATE, D.DETAIL_RETURNDATE, D.DETAIL_DAILYLATEFEE 
      FROM inserted I INNER JOIN DELETED D ON I.Rent_Num = D.Rent_Num AND I.Vid_Num = D.Vid_Num 

     DECLARE @RENT_NUM INT 
     DECLARE @RETURN_DATE_NEW DATETIME 
     DECLARE @DUE_DATE_OLD DATETIME 
     DECLARE @DUE_DATE_NEW DATETIME 
     DECLARE @RETURN_DATE_OLD DATETIME 
     DECLARE @DAILY_LATE_FEE_NEW DECIMAL(5,2) 
     DECLARE @DAILY_LATE_FEE_OLD DECIMAL(5,2) 
     DECLARE @LATE_FEE_PRIOR DECIMAL(5,2) 
     DECLARE @LATE_FEE_AFTER DECIMAL(5,2) 
     DECLARE @CHANGE DECIMAL (5,2) 

     OPEN CURSORFORUPDATE 
     FETCH NEXT FROM CURSORFORUPDATE 
     INTO @RENT_NUM, @DUE_DATE_NEW, @RETURN_DATE_NEW, @DAILY_LATE_FEE_NEW, 
       @DUE_DATE_OLD, @RETURN_DATE_OLD, @DAILY_LATE_FEE_OLD 

     WHILE (@@FETCH_STATUS = 0) 
     BEGIN 
      --A 
      IF(@RETURN_DATE_OLD > @DUE_DATE_OLD) 
       SELECT @LATE_FEE_PRIOR = DATEDIFF(DAY, @DUE_DATE_OLD, @RETURN_DATE_OLD) * @DAILY_LATE_FEE_OLD; 
      ELSE 
       SELECT @LATE_FEE_PRIOR = 0; 

      --B 
      IF(@RETURN_DATE_NEW > @DUE_DATE_NEW) 
       SELECT @LATE_FEE_AFTER = DATEDIFF(DAY, @DUE_DATE_NEW, @RETURN_DATE_NEW) * @DAILY_LATE_FEE_NEW 
      ELSE 
       SELECT @LATE_FEE_AFTER = 0 

      --C 
      SELECT @CHANGE = @LATE_FEE_AFTER - @LATE_FEE_PRIOR 

      --D 
      IF(@CHANGE <> 0) 
      BEGIN 
       DECLARE @MEM_NUM INT; 
       SELECT @MEM_NUM = M.Mem_Num 
        FROM RENTAL R 
        INNER JOIN MEMBERSHIP M ON R.MEM_NUM = M.MEM_NUM AND R.RENT_NUM = @RENT_NUM 

       UPDATE MEMBERSHIP 
        SET Mem_Balance = MEM_BALANCE + @CHANGE 
        WHERE Mem_Num = @MEM_NUM 
      END -- End of IF(@CHANGE <> 0) 

      FETCH NEXT FROM CURSORFORUPDATE 
      INTO @RENT_NUM, @DUE_DATE_NEW, @RETURN_DATE_NEW, @DAILY_LATE_FEE_NEW, 
       @DUE_DATE_OLD, @RETURN_DATE_OLD, @DAILY_LATE_FEE_OLD 
     END -- End of WHILE (@@FETCH_STATUS = 0) 

     CLOSE CURSORFORUPDATE 
     DEALLOCATE CURSORFORUPDATE 
    END -- End of IF(EXISTS (Select * From Inserted) AND EXISTS (Select * From Deleted)) 
END -- end of trigger 

кажется, что, когда ты перейдите к выбору из курсора во второй раз, переменные, которые вы перечисляете, находятся в другом порядке в первый раз. Поэтому вы пытаетесь вставить из DETAIL_DAILYLATEFEE в @RETURN_DATE_NEW и с DETAIL_RETURNDATE в @DAILY_LATE_FEE_NEW.

Я думаю, что могут быть некоторые проблемы с сопоставлением BEGIN ... END.

Редактировать

Вот мой тестовый сценарий, кажется, что все работает правильно здесь.

Create Table Rental (
    Rent_Num int, 
    Mem_Num int); 
Create Table DetailRental (
    Rent_Num int, 
    Vid_Num int, 
    Detail_DueDate datetime, 
    Detail_ReturnDate datetime, 
    Detail_DailyLateFee decimal(5,2)); 
Create Table Membership (
    Mem_Num int, 
    Mem_Balance money); 

Insert Into Membership Values (1, 0); 
Insert Into Rental Values (1, 1); 
Insert Into DetailRental 
Values (1, 1, '2016-11-21', '2016-11-23', 1), 
     (1, 2, '2015-11-21', '2016-11-22', 0.5); 
Go 

Затем создайте триггер на таблицу, в соответствии с предыдущего листинга

Select * From DetailRental; 
Select * From Rental; 
Select * From Membership; 

Update DetailRental 
    Set Detail_ReturnDate = '2016-11-21' 
    Where Rent_Num = 1; 

Select * From Membership; 
Go 

Перед

Mem_Num Mem_Balance 
1  0.00 

После

Mem_Num Mem_Balance 
1  2.00 
+0

Спасибо, что ответили. Сначала я сделал новый стиль заявления на обновление, и он не сработал. Затем я изменил порядок переменных в операторах выборки, чтобы они соответствовали друг другу, и снова попытался выполнить операцию обновления, и это все еще не сработало. Я получил эту ошибку: «преобразование завершилось неудачей при преобразовании даты и/или времени из символьной строки».Когда я попробовал свое заявление об обновлении оригинальным способом, у меня было это, я получил сообщение об ошибке «» Курсор с именем «CURSORFORUPDATE» не существует. Я не понимаю, как он говорит, что он не существует, если он вытаскивает имя курсора из курсора? –

+0

@AustinWeller Можем ли мы продолжить в чате: http://chat.stackexchange.com/rooms/48862/chat-for-conversion-error-in-curosr – mendosi

+0

Я бы не стал против этого, но моя репутация на этом сайте недостаточно высоко, чтобы поболтать, чтобы пообщаться –

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