Sql 创建存储过程以按case语句更新列

Sql 创建存储过程以按case语句更新列,sql,sql-server,tsql,sql-update,dynamic-sql,Sql,Sql Server,Tsql,Sql Update,Dynamic Sql,我知道这方面有很多问题,但我找不到答案 我有一张这样的桌子: +----+--------+--------+----------+ | ID | FormID | ItemID | StrataID | +----+--------+--------+----------+ | a | b | 1111 | NULL | | a | b | 2222 | NULL | | a | b | 3333 | NULL

我知道这方面有很多问题,但我找不到答案

我有一张这样的桌子:

+----+--------+--------+----------+
| ID | FormID | ItemID | StrataID |  
+----+--------+--------+----------+
| a  | b      |   1111 | NULL     |  
| a  | b      |   2222 | NULL     |  
| a  | b      |   3333 | NULL     |  
| a  | g      |   4563 | NULL     |  
| b  | f      |   6666 | NULL     |  
+----+--------+--------+----------+
 UPDATE [Table1]
    SET [StrataID] = 
        CASE ([ItemID])
            when 111  then 1
            when 222 then 2
            when 333 then 5
        else [StrataID]
        END 
WHERE [ID] = 'a'and [FormID] = 'b'
我想根据StrataID的ID+FormID+ItemID更新其值。我想插入的值没有存储在数据库中的任何表中,它们只是我拥有的一个单独的列表。 如果我使用常规case语句来更新表,则如下所示:

+----+--------+--------+----------+
| ID | FormID | ItemID | StrataID |  
+----+--------+--------+----------+
| a  | b      |   1111 | NULL     |  
| a  | b      |   2222 | NULL     |  
| a  | b      |   3333 | NULL     |  
| a  | g      |   4563 | NULL     |  
| b  | f      |   6666 | NULL     |  
+----+--------+--------+----------+
 UPDATE [Table1]
    SET [StrataID] = 
        CASE ([ItemID])
            when 111  then 1
            when 222 then 2
            when 333 then 5
        else [StrataID]
        END 
WHERE [ID] = 'a'and [FormID] = 'b'
因此,最终结果是:

+----+--------+--------+----------+--+
| ID | FormID | ItemID | StrataID |  |
+----+--------+--------+----------+--+
| a  | b      |   1111 | 1        |  |
| a  | b      |   2222 | 2        |  |
| a  | b      |   3333 | 5        |  |
| a  | g      |   4563 | NULL     |  |
| b  | f      |   6666 | NULL     |  |
+----+--------+--------+-------
但我希望避免对每个FormID重复case语句,因为我有2000多条记录要以这种方式更新

我尝试了以下动态sql,其中@ColumnName是特定ID+FormID的所有可用FormID,@NewValue是我希望插入到“StrataID”字段而不是空字段的值字符串:

DECLARE @DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE @ColumnName AS NVARCHAR(MAX)
DECLARE @NewValue AS NVARCHAR(MAX)


SELECT @ColumnName = STUFF((SELECT distinct  ',' +  QUOTENAME(ItemID)
                      FROM [Table1] 
                      where [ID] = 'a'and [FormID] = 'b'
                      FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') , 1, 1, '');

SET @NewValue = ',1,2,5,';


SET @DynamicPivotQuery = 

    'UPDATE [Table1] SET [StrataID] = '+@NewValue+'
     WHERE[ID] = ''a'' and [FormID] = ''b'' AND ItemID ='+@ColumnName+';' 

--Execute the Dynamic Query
EXEC sp_executesql @DynamicPivotQuery
当我试图执行它时,我得到一个错误-

Msg 137, Level 15, State 2, Line 18
Must declare the scalar variable "@NewValue".
我知道它可能将@NewValue视为字符串而不是整数,但我不确定如何以不同方式存储需要设置为新值的值,以及如何从重复的case语句创建动态sql语句

关于如何将我的sql转换为动态更新sql,有什么建议吗?
提前谢谢

通过查看您的查询,我注意到的第一件事是update column value和ItemID缺少一个引号,应该在中而不是=中,因为您有多个列名。 它应该是“SET[StrataID]=''+@NewValue+'',其中[ID]=''a''和[FormID]=''b''[SectionID]=1和'+@ColumnName+'中的ItemID;”


打印@DynamicPivotQuery并执行以查看实际错误。发送实际的更新语句和错误以查找问题。

在连接部件以形成动态查询时,您需要确保所有内容都是
nvarchar
类型,否则会出现错误。因此,您应该使用以下代码比你现在拥有的还要多

请注意,在下面的代码中,所有参数值都转换为nvarchar数据类型

SET @DynamicPivotQuery = 

        'UPDATE [Table1] SET [StrataID] = '+ cast(@NewValue as nvarchar(100)) +'
         WHERE[ID] = ''a'' and [FormID] = ''b'' 
           AND ItemID ='+ cast( @ColumnName as nvarchar(500)) +';'
但是,您不需要动态查询来处理您的场景,而是遵循下面的方法

  • 在这种方法中,您将在表中收集所有ItemId值 变量
    @ItemValues
    和 表变量
    @StrataIDValues
  • 确保两个表中的值顺序相同,以便 @ItemValues表中的第一条记录对应于中的第一条记录 @StrataIdValues表格

    不使用动态查询进行更新

    DECLARE @ItemValues TABLE (
     SequenceNumber int IDENTITY (1, 1),
     ItemID int
    )
    INSERT INTO @ItemValues (ItemID)
    SELECT
     ItemId
    FROM Table1
    WHERE [ID] = 'a'
    AND [FormID] = 'b';
    
    --populate the corresponding values for StrataID in same sequence as
    --ItemId values in above table
    DECLARE @StrataIDValues TABLE (
      SequenceNumber int IDENTITY (1, 1),
      StrataID int
    )
    INSERT INTO @StrataIDValues (StrataID)
    VALUES (1), (2), (5);
    
    UPDATE [Table1]
     SET [StrataID] = v.StrataID
     FROM Table1 t
      INNER JOIN (SELECT
                   ItemID,
                   StrataID
                FROM @ItemValues
        INNER JOIN @StrataIDValues
     ON [@ItemValues].SequenceNumber = [@StrataIDValues].SequenceNumber) v
     ON t.ItemID = v.ItemID;
    

  • 您得到的错误是什么?请打印出创建的动态sql,而不是Exec,让我们看看它是什么样子。请花更多时间提供更多详细信息并提供准确的示例。您的两个代码块都引用了不同的表,都没有或没有完成。请提供@dancingbool所述的“打印”以及您希望它执行的内容看起来像是在使用相同的表。@DancingFool感谢您的反馈-我已经更新了mu问题,以显示我的输入表、所需的输出和错误消息。您的更改列表来自哪里?您说它不在数据库中,但它必须来自某个地方-该列表看起来像什么?它是否有FormID列表和ea的更改ch one还是什么?我不确定应该向动态SQL输入什么谢谢你的回复!你发送的查询正是我需要的!!