代码之家  ›  专栏  ›  技术社区  ›  StealthRT

正在更新SQL Server查询循环,直到达到X号

  •  0
  • StealthRT  · 技术社区  · 7 年前

    我需要同时更新数据库中的几行。现在的问题是,我只知道第一行的唯一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 第一排 需要更新,但是 之后的每一行 那我 不知道

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

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

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

    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 
       ???? = ????;
    

    所以这里的问题是-我怎么能 循环浏览下x行 更新 2,3,…@val1中的值(跳过已经通过guid保存的第一个值)?

    2 回复  |  直到 7 年前
        1
  •  1
  •   DhruvJoshi    7 年前

    您可以将其视为需要更新的间隙和孤岛类型问题和孤岛行(包含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
    
        2
  •  1
  •   Gordon Linoff    7 年前

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

    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;