更新SQL Server查询循环,直到达到X数

时间:2018-05-28 20:20:57

标签: c# sql sql-server sql-server-2016

我需要同时更新数据库中的几行。现在的问题是我只会知道FIRST行的唯一ID,但之后我会有其他行的X个数,这些行也需要更新一些数据。我会知道为了更新它们需要多少循环 - 只需要知道如何去做。

我的查询如下:

UPDATE bLine 
SET @val1 
WHERE theGuid = @val2;

现在@ val1的数据如下所示:

ID | qty_SerialNum | qty_Location | qty_Property | theGUID 
---+---------------+--------------+--------------+---------------------------
5  | 6845fg56      | Home         | NA           | a45vz-u300-2bd-4710j-vf09
6  | fk469fkh      | Dock#4       | NA           |
7  | geww2         | Dock#1       | Local        |
...

当在字符串中为 @ val1 发送时

@val1 = qty_SerialNum = '6845fg56,fk469fkh,geww2',
        qty_Location = 'Home,Dock#4,Dock#1',
        qty_Property = 'NA,NA,Local' 
@val2 = theGUID = 'a45vz-u300-2bd-4710j-vf09'

所以这一切都很好,因为我知道需要更新的第一行 GUID ,但 之后的每一行不会知道

所以第一次更新看起来像3:

UPDATE
   bLine
SET
   (qty_SerialNum = '6845fg56',qty_Location = 'Home',qty_Property = 'NA' )
WHERE 
   theGuid = 'a45vz-u300-2bd-4710j-vf09';

这将是3中的第二次更新:

UPDATE
   bLine
SET
   (qty_SerialNum = 'fk469fkh',qty_Location = 'Dock#4',qty_Property = 'NA' )
WHERE 
   ???? = ????;

最后这将是3中的第3次更新:

UPDATE
   bLine
SET
   (qty_SerialNum = 'geww2',qty_Location = 'Dock#1',qty_Property = 'Local' )
WHERE 
   ???? = ????;

所以这里的问题是 - 我如何在@ val1中使用2,3,...值遍历下一行X 更新这些信息跳过第一个,因为它已经通过theGUID保存了吗?

2 个答案:

答案 0 :(得分:1)

你有一个非常神秘的问题。通常,SQL更新不适用于" adjancent"以这种方式排。但是,您可以通过将值存储在(虚拟)表中并将两者连接在一起来使其工作:

with v as (
      select v.*
      from (values (1, '6845fg56', 'Home', 'NA'),
                   (2, 'fk469fkh', 'Dock#4', 'NA'),
                   (3, 'geww2', 'Dock#1', 'Local')
           ) v(seqnum, qty_SerialNum, qty_Location, qty_Property)
     )
update b
   set qty_SerialNum = v.qty_SerialNum,
       qty_Location = v.qty_Location,
       qty_Property = v.qty_Property
    from (select top(3) b.*,
                 row_number() over (order by id) as seqnum
          from bline b
          where id >= (select id from bline where theGUID = 'a45vz-u300-2bd-4710j-vf09'
          order by id
         ) b join
         v
         on b.seqnum = v.seqnum;

答案 1 :(得分:1)

您可以将此视为间隙和岛屿类型问题,您需要更新和岛屿行(包含guid的行以及所有间隙行直到下一个岛)。

我在这里采取一些假设,下面是 working demo

create table bline (ID int, qty_SerialNum varchar(100),qty_Location varchar(100),qty_Property varchar(100), theGUID  varchar(100))
insert into bline values 
(5,'random','garbage','existing','a45vz-u300-2bd-4710j-vf09')
,(6,'data','random','garbage', NULL)
,(7,'existing','data','.', NULL);

create table #V (qty_SerialNum varchar(100),qty_Location varchar(100),qty_Property varchar(100))
insert into #V values
('6845fg56','Home','NA'),
('fk469fkh','Dock#4','NA'),
('geww2','Dock#1','Local')


;with map as
  (
       select id, 
          rn=row_number() over ( order by id asc) 
       from bline 
          where theGUID is NOT NULL
   ),
mappedBline as
   (
       select 
           b1.*,
           rn
       from
           bline b1 join
       (
           select b.id,
               rn=max(rn)
           from bline b 
               join map m
                   on b.id >=m.id
           group by b.id
         )b2 
       on b2.id=b1.id
     ),
updateSet as
    (
        select 
            M.*, 
            updaterow=row_number() over( order by M.id)
        from mappedBline M join
          mappedBline M2 
              on M.rn=M2.rn 
                and M2.theGUID = 'a45vz-u300-2bd-4710j-vf09' --@val2
     )

 update U
     set
         qty_SerialNum=V.qty_SerialNum,
         qty_Location= V.qty_Location,
         qty_Property =V.qty_Property
 from
 updateSet U join
 ( select 
      *, updaterow =row_number() over (order by (select NULL))
  from #V
  )V
  on U.updaterow=V.updaterow

select * from bline