运行简单的更新语句时,我一直收到此错误。
Msg 16922,Level 16,State 1,Procedure TRG_MEM_BALANCE_AWW,Line 72
光标提取:不允许从数据类型datetime到decimal的隐式转换。
这是我的触发器代码。我没有看到错误转换的内容?
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表中返回,这应该更新MEMBERSHIP表中的成员余额。任何有关如何解决此错误的想法都将不胜感激。
答案 0 :(得分: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