SQL - 更新以将值放入编号列

时间:2017-09-26 17:02:49

标签: sql sql-server-2012 ssms

我有一组查询来根据序列号使用另一个表(boxes)中的代码更新表(cards)。序列号为1的卡进入表code_1中名为boxes的列中,依此类推,以获得有限数量的可能序列号。由于它是有限的,我可以做类似的事情:

update b
    set code_1 = c.codes
    from boxes as b inner join cards as c
        on b.service_id = c.service_id and c.sequence_number = 1;
update b
    set code_2 = c.codes
    from boxes as b inner join cards as c
        on b.service_id = c.service_id and c.sequence_number = 2;
update b
    set code_3 = c.codes
    from boxes as b inner join cards as c
        on b.service_id = c.service_id and c.sequence_number = 3;
...
update b
    set code_n = c.codes
    from boxes as b inner join cards as c
        on b.service_id = c.service_id and c.sequence_number = n;

但我的问题是:有没有办法编写单个查询,根据源中的序列号适当更新所有列?

5 个答案:

答案 0 :(得分:0)

您可以使用以下代码

执行此操作
UPDATE b
    SET code_1 = CASE sequence_number
        WHEN 1 THEN 3
        WHEN 2 THEN 4
        WHEN 3 THEN 5
    END,
    code_2 = CASE sequence_number
        WHEN 1 THEN 'New Title 1'
        WHEN 2 THEN 'New Title 2'
        WHEN 3 THEN 'New Title 3'
    END
WHERE sequence_number IN (1,2)

据我所知,您可以使用多个来实现多个更新。希望这会对你有所帮助。

答案 1 :(得分:0)

update b set code_1 = (select c.codes from cards as c on b.service_id = i.service_id and c.sequence_number = 1), 
code_2= (select c.codes from cards as c on b.service_id = i.service_id and c.sequence_number = 2),
code_3= (select c.codes from cards as c on b.service_id = i.service_id and c.sequence_number = 3),
. 
. 
. 
code_n= (select c.codes from cards as c on b.service_id = i.service_id and c.sequence_number = n);

答案 2 :(得分:0)

嗯......如果你不想硬编码,也许你可以使用带循环的方法。我在sp中并不是超级强者,但是这样的话:

DECLARE @LoopCounter INT = 1, @codeNumber int;

WHILE (SELECT boxID FROM boxes )< (select max(boxID) as boxIDMax from boxes )
BEGIN  
SET @codeNumber= <get_your_codeID_here_with_select_where_boxID=codeID>

update b
    set @codeNumber = c.codes
    from boxes as b inner join cards as c
        on b.service_id = i.service_id and c.sequence_number = boxID;

SET @LoopCounter  = @LoopCounter  + 1;  

END

答案 3 :(得分:0)

您可以使用<cfloop index="i" from="1" to="#arrayLen(myArray)#"> <cfif directoryExists("#myArray[i][1]#")> it exists. <cfelse> Doesn't exists. </cfif> </cfloop>

制作
PIVOT

答案 4 :(得分:0)

在设计时不知道要更新的列数这一事实意味着严格来说,这不能在单个查询中完成。您需要构建然后执行动态SQL查询才能执行此操作。

@Troels答案是在N上接近此循环的一种方法,并且对于每次迭代发布和更新。这将是比您目前更方便的代码,可能是您真正想要的,但不是单个查询。

要使其成为单个查询,您必须:

  • 使用N“Items”
  • 动态构建查询
  • 首先建立从Boxes到卡片的连接
  • 将其用作pivot语句中的子查询,为每个Item生成一列(这是动态SQL必需的位置)
  • 将数据透视查询作为CTE的第一部分
  • 接下来,通过service_id
  • 将框连接到CTE表集上
  • 将其设置为更新语句,在Set子句中使用N(动态生成的)项,并将值设置为数据透视表集中的相应列(并确保正确检查并处理NULL)

这将是一个痛苦的写作和一个轻微的头痛,随着时间的推移做出改变。除非有一个非常强大的理由(需要单个事务?)我将从@Troels版本开始并添加动态SQL。

如果当然必须说最好的解决方案是规范化表boxes,使其不包含未知数量的行 - 比如Boxes(主键{{1 }}和BoxContents(主键box_id

... @ sarslan的支点回答是在我写这篇文章的时候出现的,而且正是我所说的。如果你知道N就可以工作,但是如果你不知道就必须建立并专门运行。