在动态SQL中将变量用作列名的一部分

在动态SQL中将变量用作列名的一部分,sql,sql-server,dynamic-sql,Sql,Sql Server,Dynamic Sql,我试图在动态SQL语句中将变量用作列名的一部分 我有4列,分别称为Player1Action,Player2Action,Player3Action和Player4Action 根据变量@CurrentPlayerId,我想用一些数据更新相关的player列 例如,如果CurrentPlayerId包含1,则更新列Player1Action 我意识到我可以通过一系列IF语句来实现这一点,但我希望以更干净的方式来实现 我有以下代码,但我认为我的转义导致了问题。我已经多次重写了这个视图,但我似乎无法

我试图在动态SQL语句中将变量用作列名的一部分

我有4列,分别称为
Player1Action
Player2Action
Player3Action
Player4Action

根据变量
@CurrentPlayerId
,我想用一些数据更新相关的player列

例如,如果CurrentPlayerId包含
1
,则更新列
Player1Action

我意识到我可以通过一系列IF语句来实现这一点,但我希望以更干净的方式来实现

我有以下代码,但我认为我的转义导致了问题。我已经多次重写了这个视图,但我似乎无法让它工作

DECLARE
@CurrentPlayerId INT,
@CurrentPlayerBetAmount nvarchar(MAX),
@stmt nvarchar(MAX);

SET @CurrentPlayerId = 1
SET @CurrentPlayerBetAmount = 100

SET @stmt = N'UPDATE HandCurrent SET ''Player'' ''+'' @CurrentPlayerId ''+'' ''Action'' = 1 '','' ''Player'' ''+'' @CurrentPlayerId ''+'' ''ActionSize'' = @CurrentPlayerBetAmount'

EXECUTE sp_executesql @stmt
如果我将其作为select运行,则返回以下内容

UPDATE HandCurrent SET 'Player' '+' @CurrentPlayerId '+' 'Action' = 1 ',' 'Player' '+' @CurrentPlayerId '+' 'ActionSize' = @CurrentPlayerBetAmount

不要引用变量

SET @stmt = N'UPDATE HandCurrent SET 
            Player' + @CurrentPlayerId + 'Action = 1, 
            Player' + @CurrentPlayerId + 'ActionSize = ' + @CurrentPlayerBetAmount

不要引用变量

SET @stmt = N'UPDATE HandCurrent SET 
            Player' + @CurrentPlayerId + 'Action = 1, 
            Player' + @CurrentPlayerId + 'ActionSize = ' + @CurrentPlayerBetAmount
Juan Carlos说得对唯一的问题是变量的数据类型
@CurrentPlayerId
是一个INT,所以您需要将它转换为
NVARCHAR()

为了保持一致,您还应该将
@CurrentPlayerBetAmount
声明为
INT
。如果你这样做了,那么你也需要投下它

但是,您也可以简单地将两者声明为
NVARCAHR(MAX)
,然后在设置时单引号引用该值,例如:

DECLARE
@CurrentPlayerId NVARCHAR(MAX),
@CurrentPlayerBetAmount NVARCHAR(MAX),
@stmt nvarchar(MAX);

SET @CurrentPlayerId = '1'
SET @CurrentPlayerBetAmount = '100'

SET @stmt = N'UPDATE HandCurrent SET 
            Player' + @CurrentPlayerId + 'Action = 1, 
            Player' + @CurrentPlayerId + 'ActionSize = ' + @CurrentPlayerBetAmount

EXECUTE sp_executesql @stmt
或者,如果您要更改记录,我的首选方法是,如果您有4列,只执行update语句。您还可以考虑对列进行n次规范化并使其成为行

DECLARE @CurrentPlayerId INT = 1
DECLARE @CurrentPlayerBetAmount INT = 100

UPDATE HandCurrent
    Player1Action = CASE WHEN @CurrentPlayerId = 1 THEN 1 ELSE PlayerAction1 END
    ,Player1ActionSize = CASE WHEN @CurrentPlayerId = 1 THEN @CurrentPlayerBetAmount ELSE Player1ActionSize END
    ,Player2Action = CASE WHEN @CurrentPlayerId = 2 THEN 1 ELSE PlayerAction2 END
    ,Player2ActionSize = CASE WHEN @CurrentPlayerId = 2 THEN @CurrentPlayerBetAmount ELSE Player2ActionSize END
    ,Player3Action = CASE WHEN @CurrentPlayerId = 3 THEN 1 ELSE PlayerAction3 END
    ,Player3ActionSize = CASE WHEN @CurrentPlayerId = 3 THEN @CurrentPlayerBetAmount ELSE Player3ActionSize END
    ,Player4Action = CASE WHEN @CurrentPlayerId = 4 THEN 1 ELSE PlayerAction4 END
    ,Player4ActionSize = CASE WHEN @CurrentPlayerId = 4 THEN @CurrentPlayerBetAmount ELSE Player4ActionSize END
WHERE
    ????
注意,您实际上正在更新整个表,这是您想要的吗

Juan Carlos说得对唯一的问题是变量的数据类型
@CurrentPlayerId
是一个INT,所以您需要将它转换为
NVARCHAR()

为了保持一致,您还应该将
@CurrentPlayerBetAmount
声明为
INT
。如果你这样做了,那么你也需要投下它

但是,您也可以简单地将两者声明为
NVARCAHR(MAX)
,然后在设置时单引号引用该值,例如:

DECLARE
@CurrentPlayerId NVARCHAR(MAX),
@CurrentPlayerBetAmount NVARCHAR(MAX),
@stmt nvarchar(MAX);

SET @CurrentPlayerId = '1'
SET @CurrentPlayerBetAmount = '100'

SET @stmt = N'UPDATE HandCurrent SET 
            Player' + @CurrentPlayerId + 'Action = 1, 
            Player' + @CurrentPlayerId + 'ActionSize = ' + @CurrentPlayerBetAmount

EXECUTE sp_executesql @stmt
或者,如果您要更改记录,我的首选方法是,如果您有4列,只执行update语句。您还可以考虑对列进行n次规范化并使其成为行

DECLARE @CurrentPlayerId INT = 1
DECLARE @CurrentPlayerBetAmount INT = 100

UPDATE HandCurrent
    Player1Action = CASE WHEN @CurrentPlayerId = 1 THEN 1 ELSE PlayerAction1 END
    ,Player1ActionSize = CASE WHEN @CurrentPlayerId = 1 THEN @CurrentPlayerBetAmount ELSE Player1ActionSize END
    ,Player2Action = CASE WHEN @CurrentPlayerId = 2 THEN 1 ELSE PlayerAction2 END
    ,Player2ActionSize = CASE WHEN @CurrentPlayerId = 2 THEN @CurrentPlayerBetAmount ELSE Player2ActionSize END
    ,Player3Action = CASE WHEN @CurrentPlayerId = 3 THEN 1 ELSE PlayerAction3 END
    ,Player3ActionSize = CASE WHEN @CurrentPlayerId = 3 THEN @CurrentPlayerBetAmount ELSE Player3ActionSize END
    ,Player4Action = CASE WHEN @CurrentPlayerId = 4 THEN 1 ELSE PlayerAction4 END
    ,Player4ActionSize = CASE WHEN @CurrentPlayerId = 4 THEN @CurrentPlayerBetAmount ELSE Player4ActionSize END
WHERE
    ????

注意,您实际上是在更新整个表,这是您想要的吗?

说到最干净的方法,最好的方法是使用带有参数的
sp_executesql
,这意味着
@CurrentPlayerId
@CurrentPlayerBetAmount
是给定代码的输入参数:

Declare @sql nvarchar(256)
    , @sql1 nvarchar(256) = N'update HandCurrent
    Set Player1Action =@value,
    Player1ActionSize =@size'
    , @sql2 nvarchar(256) = N'update HandCurrent
    Set Player2Action =@value,
    Player2ActionSize =@size'
    , @params nvarchar (128)
    , @CurrentPlayerId int
    ;

Select @sql = case @CurrentPlayerId when 1 then @sql1 when 2 then @sql2 else '' end;
If @sql <> '' begin
  set @params = N'@value int, @size int';
  execute sp_executesql @sql, @params,
        @value =1,
        @size = @CurrentPlayerBetAmount
        ;
End
Declare@sql-nvarchar(256)
,@sql1 nvarchar(256)=N'update HandCurrent
设置Player1Action=@value,
Player1ActionSize=@size'
,@sql2 nvarchar(256)=N'update HandCurrent
设置Player2Action=@value,
Player2ActionSize=@size'
,@params nvarchar(128)
,@CurrentPlayerId int
;
选择@sql=case@CurrentPlayerId when 1,然后选择@sql1 when 2,然后选择@sql2 else''end;
如果@sql“”开始
设置@params=N'@value int,@size int';
执行sp_executesql@sql、@params、,
@值=1,
@大小=@CurrentPlayerBetAmount
;
终点

说到最干净的方法,最好的方法是使用带有参数的
sp_executesql
,这意味着
@CurrentPlayerId
@CurrentPlayerBetAmount
是给定代码的输入参数:

Declare @sql nvarchar(256)
    , @sql1 nvarchar(256) = N'update HandCurrent
    Set Player1Action =@value,
    Player1ActionSize =@size'
    , @sql2 nvarchar(256) = N'update HandCurrent
    Set Player2Action =@value,
    Player2ActionSize =@size'
    , @params nvarchar (128)
    , @CurrentPlayerId int
    ;

Select @sql = case @CurrentPlayerId when 1 then @sql1 when 2 then @sql2 else '' end;
If @sql <> '' begin
  set @params = N'@value int, @size int';
  execute sp_executesql @sql, @params,
        @value =1,
        @size = @CurrentPlayerBetAmount
        ;
End
Declare@sql-nvarchar(256)
,@sql1 nvarchar(256)=N'update HandCurrent
设置Player1Action=@value,
Player1ActionSize=@size'
,@sql2 nvarchar(256)=N'update HandCurrent
设置Player2Action=@value,
Player2ActionSize=@size'
,@params nvarchar(128)
,@CurrentPlayerId int
;
选择@sql=case@CurrentPlayerId when 1,然后选择@sql1 when 2,然后选择@sql2 else''end;
如果@sql“”开始
设置@params=N'@value int,@size int';
执行sp_executesql@sql、@params、,
@值=1,
@大小=@CurrentPlayerBetAmount
;
终点


请用您正在使用的RDBMS标记问题为什么不
选择@stmt
查看结果sql?@Kacper完成,谢谢@JuanCarlosOropeza我试过这样做,但结果并不能真正向我解释它出了什么问题。如果有帮助,我可以发布select的输出?请这样做,这有助于查看问题请用您正在使用的RDBMS标记问题为什么不做
select@stmt
查看结果sql?@Kacper完成,谢谢@JuanCarlosOropeza我试过这样做,但结果并不能真正向我解释它出了什么问题。如果有帮助,我可以发布select的输出?请这样做,这有助于查看问题。也不要引用运算符。OP有双单引号。谢谢你的建议,这对我不起作用,因为它似乎表明缺少qoute。@JuanCarlosOropeza现在正在抱怨转换错误。“将nvarchar值'UPDATE HandCurrent SET Player'转换为数据类型int时,Msg 245,16级,状态1,第9行转换失败。”
Player1ActionSize
is string?@CurrentPlayerId是int,需要转换为nvarchar()。。。o将变量改为nvarchar而不是INT。这就是CurrentPlayerBetAmount也不引用运算符的原因。OP有双单引号。谢谢你的建议,这对我不起作用,因为它似乎表明缺少qoute。@JuanCarlosOropeza现在正在抱怨转换错误。“将nvarchar值'UPDATE HandCurrent SET Player'转换为数据类型int时,Msg 245,16级,状态1,第9行转换失败。”
Player1ActionSize
is string?@CurrentPlayerId是int,需要转换为nvarchar()。。。o将变量改为nvarchar而不是INT。这就是CurrentPlayerBetAmount的方式。虽然我同意将动态sql参数化,但问题是参数用于动态