我必须编写一个存储过程,您可以在其中提供月份和信用卡号,并且在每月的前10天中进行的每笔交易计算1%,对于10到20之间的交易计算2%, 20岁以上的交易占3%。 我必须使用游标。
我写了这段代码,但是当我尝试运行precedure时出现了一些错误
create procedure cardP
/* month ex 1,3,5 etc*/
@minas int,
@cardNo bigint
as
/* creating the cursor*/
DECLARE sinallages CURSOR
FOR SELECT cc_number,day([DateTime]),charged_amount FROM transactions
where cc_number=@cardNo and month([DateTime])=@minas
/* declaring local variables*/
declare @poso int,@karta bigint,@mera int,@pos float,@pos2 float,@pos3 float,
@count int,@counter int
open sinallages
set @count=(select count(cc_number) from transactions where cc_number=@cardNo and month([DateTime])=@minas )
/* get 1st row*/
fetch sinallages into @karta,@mera,@poso
while (/*@@sqlstatus != 2*/@counter<@count)
begin
if day(@mera)<=10
set @pos =@poso+ @poso * 0.01
else
if day(@mera)>10 and day(@mera)<=20
set @pos2 =@poso+ @poso * 0.02
else
if day(@mera) > 20
set @pos3 =@poso+ @poso * 0.03
fetch sinallages into @karta,@mera,@poso
set @counter=@counter+1
end
close sinallages
return
当我打电话给我的程序时
EXEC cardP @minas = 5,@ cardNo = 4929569752542450
Msg 16915, Level 16, State 1, Procedure cardP, Line 20
A cursor with the name 'sinallages' already exists.
Msg 16922, Level 16, State 1, Procedure cardP, Line 31
Cursor Fetch:不允许从数据类型datetime到int的隐式转换。
谢谢:)我现在在存储过程的末尾取消分配光标并删除day()。现在我要打印pos + pos2 + pos3。我使用print pos + pos2 + pos3但它不打印任何东西。这是为什么 ??
................
set @counter=@counter+1
end
print @pos+@pos2+@pos3
close sinallages
return
DEALLOCATE sinallages;
似乎hte变量po,pos2,pos3都保留为null ??
答案 0 :(得分:3)
其他人建议使用DEALLOCATE。问题在于,在某些错误情况下,它不会被调用。如果您随后尝试使用相同的连接来调用此存储过程,则仍将分配游标。
我宁愿改为declare the cursor as LOCAL,这意味着当退出存储过程时(无论是否正常),它会自动解除分配。
答案 1 :(得分:1)
答案 2 :(得分:1)
是的,您需要在关闭游标后释放游标。此外,如果您的查询在关闭游标之前有错误,它可能保持打开状态,因此我建议您在再次执行程序之前执行CLOSE
和DEALLOCATE
。对于第二个错误,您使用的函数DAY()
优先于INT
类型的变量,使用if day(@mera)<=10
更改if @mera<=10
。
更新现在您已经解决了问题,当您添加每个@pos变量时,按照您的逻辑,其中一个始终为null,因此您应该像这样添加它们:
打印isnull(@ pos1,0)+ isnull(@ pos2,0)+ isnull(@ pos3,0)
答案 3 :(得分:0)