【问题标题】:Msg 137, Must declare the scalar variableMsg 137, 必须声明标量变量
【发布时间】:2015-12-31 10:04:47
【问题描述】:
Declare @SKUCode1 varchar(30), @SKUCode2 varchar(30), @SKUCode3 varchar(30),
        @SKUCode4 varchar(30), @SKUCode5 varchar(30), @SKUCode6 varchar(30),
        @SKUCode7 varchar(30), @SKUCode7 varchar(30), @SKUCode8 varchar(30),
        @SKUCode10 varchar(30), @Temp_SKU varchar(30), @SKUCodeS varchar(30),
        @sp1 nvarchar(max),@Index int

Set @SKUCodeS = 'SKUCode'
Set @Index = 0

While @Index < 10   
Begin
    Set @Index = @Index + 1  

    Select @Temp_SKU = SKUCode  
    From dbo.UDA_Order  
    Where Areaname = 'LMC-TYRE BUILDING'

    Set @sp1 = 'Set'+' '+ @SKUCodeS+CONVERT(varchar,@Index)+' '+'='+' '+'@Temp_SKU'  

    Exec sp_executesql @sp1  
End

这是抛出错误

消息 137,第 15 级,状态 2,第 1 行
必须声明标量变量“@Temp_SKU”

我不知道为什么会这样。

请帮忙。

【问题讨论】:

  • 变量是特定范围的本地变量。 Execnew 范围内运行代码。使用这些变量,您无法在此处实现您想要做的事情。您要解决什么问题
  • 这里还有其他问题 - 这可能只是由于您在发布之前简化了代码 - 但也会引发危险信号 - 例如设置@Temp_SKUSELECT 似乎并不依赖于循环。如果只有一行匹配 WHERE 子句,那么在循环中执行它是多余的。如果有多行,则无法保证每次将使用哪些行值来完成分配。一行可以全部使用十次,但这绝不能保证,而且可能不是所需的行为。
  • @Damien_The_Unbeliever - 我想获取参数“@SKUCode1”到“@SKUCode10”的值,在每次执行循环时,“@Temp_SKU”中的值应该移动到“@SKUCodeX”中X 是循环索引

标签: sql-server


【解决方案1】:

好的,所以第一个任务 - 为每个变量分配适当的值,可以这样完成:

--Sample data
declare @t table (SKUCode varchar(30) not null,MachineNo int not null)
insert into @t(SKUCode,MachineNo) values
('abc',1),
('def',2),
('ghi',3),
('jkl',4),
('mno',5),
('pqr',6),
('stu',7),
('vwx',8),
('uzA',9),
('BCD',10)

--Actual query
Declare @SKUCode1 varchar(30), @SKUCode2 varchar(30), @SKUCode3 varchar(30),
        @SKUCode4 varchar(30), @SKUCode5 varchar(30), @SKUCode6 varchar(30),
        @SKUCode7 varchar(30), @SKUCode8 varchar(30), @SKUCode9 varchar(30),
        @SKUCode10 varchar(30)

select @SKUCode1 = [1], @SKUCode2 = [2], @SKUCode3 = [3],
       @SKUCode4 = [4], @SKUCode5 = [5], @SKUCode6 = [6],
       @SKUCode7 = [7], @SKUCode8 = [8], @SKUCode9 = [9],
       @SKUCode10 = [10]
from (select * from @t pivot (MAX(SKUCode) for
      MachineNo in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10])) u
      where 1=1 --Areaname, couldn't be bothered to include it here
      ) t

select @SKUCode5

应该打印mno。而且我们避免了任何讨厌的循环、动态 SQL 等。

你的问题的下一个部分现在是否容易解决,我不知道。

【讨论】:

  • 谢谢...这是唯一有效的解决方案,我之前尝试的解决方案是不可能的,因为我试图将本地参数传递给全局。我试图保存代码的长度,但这是不可能的。
【解决方案2】:

您将@Temp_SKU 添加到动态执行的字符串中。但是,sp_execute 不知道您的上下文并且没有对@TEMP_SKU 的引用。尝试通过删除引号来添加 @Temp_SKU 的值,而不是引用变量:

 Set @sp1 = 'Set'+' '+ @SKUCodeS+CONVERT(varchar,@Index)+' '+'='+' '+ @Temp_SKU  

在调用 sp_execute 之前尝试 printing @sp1 以查看实际执行的内容。

【讨论】:

    【解决方案3】:

    您在动态查询中使用@Temp_SKU。当动态查询被触发时,您必须在动态查询的范围内声明它,我建议使用不同的名称:

    Set @sp1 = 'Set'+' '+ @SKUCodeS+CONVERT(varchar,@Index)+' '+'='+' '+'@Temp_SKUDYN'  
    Exec sp_executesql @sp1  N'@Temp_SKUDYN varchar(30)' @Temp_SKUDYN = @@Temp_SKU
    

    但是,您实际上想做什么?看起来您正在尝试动态设置局部变量。在这种情况下,你必须使用类似的东西:

    DECLARE @SQLString NVARCHAR(500)
    DECLARE @ParmDefinition NVARCHAR(500)
    DECLARE @IntVariable INT
    DECLARE @Lastlname varchar(30)
    SET @SQLString = N'SELECT @LastlnameOUT = max(lname)
                       FROM pubs.dbo.employee WHERE job_lvl = @level'
    SET @ParmDefinition = N'@level tinyint,
                            @LastlnameOUT varchar(30) OUTPUT'
    SET @IntVariable = 35
    EXECUTE sp_executesql
    @SQLString,
    @ParmDefinition,
    @level = @IntVariable,
    @LastlnameOUT=@Lastlname OUTPUT
    SELECT @Lastlname
    

    (复制自here

    编辑

    现在完全不确定这是否会成为您的解决方案。你最好解释一下你到底想要完成什么。

    编辑 2

    我仍然认为它可能更容易,但这至少更清楚(未经测试,可能需要一些工作):

    Declare @SKUCode1 varchar(30), @SKUCode2 varchar(30), @SKUCode3 varchar(30),
            @SKUCode4 varchar(30), @SKUCode5 varchar(30), @SKUCode6 varchar(30),
            @SKUCode7 varchar(30), @SKUCode8 varchar(30), @SKUCode9 varchar(30),
            @SKUCode10 varchar(30), @Temp_SKU varchar(30), @SKUCodeS varchar(30),
            @sp1 nvarchar(max),@Index int
    
    CREATE TABLE ##codes (i INT, Val VARCHAR(30))
    ;
    
    Set @SKUCodeS = 'SKUCode'
    Set @Index = 0
    
    While @Index < 10   
    Begin
        Set @Index = @Index + 1  
    
        Select @Temp_SKU = SKUCode  
        From dbo.UDA_Order  
        Where Areaname = 'LMC-TYRE BUILDING'
            AND MachineNumber = @Index
    
        Set @sp1 = 'insert into ##codes(i, Val) VALUES('+ @Index + ',' + @Temp_SKU + ' )'-- 'Set'+' '+ @SKUCodeS+CONVERT(varchar,@Index)+' '+'='+' '+'@Temp_SKU'  
    
        Exec sp_executesql @sp1  
    END
    
    SELECT      @SKUCode1 = 1
    ,           @SKUCode2 = 2
    ,           @SKUCode3 = 3
    ,           @SKUCode4 = 4
    ,           @SKUCode5 = 5
    ,           @SKUCode6 = 6
    ,           @SKUCode7 = 7
    ,           @SKUCode8 = 8
    ,           @SKUCode9 = 9
    ,           @SKUCode10 = 10
    FROM        (
                    SELECT  *
                    FROM    ##codes AS C
                    PIVOT   (
                                MAX(VAL)
                                FOR i IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10])
                            ) p
                ) piv
    
    DROP TABLE ##codes
    

    【讨论】:

    • 我正在尝试获取 SKUCode1 到 SKUCode10 的值,在获得这些值之后,这些值将被传递给机器控制器。这就是我使用动态查询的原因。我错过了一件事"其中 Areaname = 'LMC-TYRE BUILDING' AND MachineNumber = @Index"
    • 在您提供的解决方案中,我需要“@LastnameOUT”作为变量,其值应从“@SKUCode1”更改为“@SKUCode10”
    • 是的,我认为您应该能够使用第二个代码块。但是,我确实认为,必须有一个更简单的方法。不过还不确定是什么
    • 您可以直接从UDA_Order 进行数据透视。无需循环、使用动态 SQL、使用临时表等。
    • @Damien_The_Unbeliever,哦,是的,看起来你是对的。陷入思维模式……
    猜你喜欢
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 2011-11-03
    • 1970-01-01
    • 2013-07-03
    • 1970-01-01
    相关资源
    最近更新 更多