将Char值转换为连接变量的money

时间:2014-01-04 09:59:43

标签: sql-server sql-server-2008 tsql

我有以下存储过程正常工作,直到我必须引入@n变量来更改新要求的过程。

ALTER procedure [dbo].[p_insertValue]  
   ,@p1001          varchar(18)
   ,@p1002          varchar(18)
   ,@p1003          varchar(18)   
as
begin
  declare @i varchar(25) 
  declare @n varchar(25) 
  declare @limit int 

  set @limit = 1004;
  set @i = 1001;

  while (@i <=@limit)
  begin
     set @n = '@'+p'+@i;
     if(@n is not null)
     begin
        if EXISTS (select Id  from t_values where Id=@i)
        begin
           update t_values 
           set  amount    =convert(varchar,cast(@n as money),2)
           where Id =@i 
        end
     end 

     set @i=@i+1;
  end  
end

当我运行该程序时,它会返回错误

  

无法将char值转换为money。 char值的语法不正确。

基本上问题在于这一行

 set @n = '@'+'p'+@i;

因为while循环通过这个假设是@ p1001,@ p1002,@ p1003所以它的值可以转换为金钱。当我尝试使用直接@ p1001等时它工作正常。

请让我知道如何更正此行,以便它可以正常工作。

1 个答案:

答案 0 :(得分:2)

您不能通过在尝试时构造其名称字符串来引用变量。

正如米奇所说,无论如何这都是非常可怕的。

  • 如果@p1001应包含money值,请使用money数据类型而不是varchar(18)
  • 为什么要将它转换为money然后再转回SET
  • 中的varchar
  • 为什么要将@i声明为varchar(25)而不是整数?
  • 不是单独将参数值@p1001传递给@p1026,而是每次需要扩展列表时添加新参数,只需传入一个表值参数。
  • 您正在逐行处理而不是基于设置。
  • 递增where Id =@i子句看起来非常可疑,因为IDENTITY值无法保证顺序。

解决这个问题的最快方法是保留高度可疑的语义,只需用

替换整个事物。
UPDATE T
SET    amount = CONVERT(VARCHAR(30), cast(V.amount AS MONEY), 2)
FROM   t_values T
       JOIN (VALUES('1001', @p1001),
                   ('1002', @p1002),
                   ('1003', @p1003)) V(Id, amount)
         ON V.Id = T.Id 

如果你可以重写整个内容,那么用带有两列正确数据类型的TVP替换VALUES子句。