6

他のエントリを見てきましたが、カーソルが必要なようです。私は比較的新しいですが、これで高くスイングしています。アドバイスやヘルプは大歓迎です。

UPDATE top (1) dbo.table
SET [Status] = 1
WHERE [OrderId] = '1337' and [Status] = 0;
GO               

OrderID が 1337 でステータスが 0 のレコードを 1 に変更したいのですが、これは一度に 1 つずつ行う必要があります。

編集:[ステータス] = 0がなくなるまでループさせたい

4

4 に答える 4

3

私の答えもミックスに入れます。小さなバッチで更新を行う必要がある本番システムでこれを使用します。1 つのバッチで実行したい場合は、 select top 100 PKidtoを変更できます。top 1この方法では、最小限のロックとセットベースの更新の間の適切な妥協点を見つけて、更新のバッチを妥当なものにスケーリングできます。明らかに、これは単一のセットベースのステートメントにオーバーヘッドを追加しますが、OP は要求しました。

注: テーブルに PK フィールドがあると推測しています。PKid

declare @done bit = 0x0;
declare @inputs table (PKid int primary key)

while @done = 0x0
begin
    -- clear the temp table variable
    delete from @inputs

    -- build the small batch up updates into table variable
    insert into @inputs (PKid) 
    select top 100 PKid from dbo.table where [Status] = 0 and OrderId = '1337'

    -- if we inserted zero records, set our @done bit to 'true' so the while loop breaks
    if @@rowcount = 0
    begin
        select @done = 0x1
    end

    -- make the update to the real table, constrained by the temp table variable
    update  t
    set     t.[Status] = 1
    from    dbo.table as t
    join    @inputs as i
    on      i.PKid = t.PKid
end
于 2013-05-28T20:55:05.713 に答える
0

この文で 1 つのレコードのみを更新する場合は、次のことをお勧めします。

UPDATE dbo.table
SET [Status] = 1
WHERE rowId in (Select top(1) rowId from dbo.Table where [OrderId] = '1337' and Status = 0);

Transact を使用しているか PL を使用しているかはわかりません。rowId を ROW_NUMBER で変更する必要があるかもしれません。一意の識別子でrowIdを変更することもできます。Where 句は、「select」句によって返される行のみに一致します。

(他の回答と同様に)更新用のカーソルを使用して実行できますが、これが1回だけの場合は、これが迅速な解決策です。

于 2013-05-28T16:51:55.177 に答える
-1

これを行うために、while またはカーソル ループを使用しないでください。

これが更新の「トップ」です.......回避策:

http://granadacoder.wordpress.com/2009/07/06/update-top-n-order-by-example/

/* START TSQL */

    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Television]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
          BEGIN
                DROP TABLE [dbo].[Television]
          END
    GO


    CREATE TABLE [dbo].[Television] (
          TelevisionUUID [uniqueidentifier] not null default NEWSEQUENTIALID() , 
          TelevisionName varchar(64) not null , 
          TelevisionKey int not null , 
          IsCheckedOut bit default 0
    )     
    GO


    ALTER TABLE dbo.Television ADD CONSTRAINT PK_Television_TelevisionUUID
    PRIMARY KEY CLUSTERED (TelevisionUUID)
    GO


    ALTER TABLE dbo.Television ADD CONSTRAINT CK_Television_TelevisionName_UNIQUE 
    UNIQUE (TelevisionName)
    GO


    set nocount on

    declare @counter int
    select @counter = 11000
    declare @currentTVName varchar(24)
    declare @TopSize int
    select @TopSize = 10

    while @counter > 10000  /* this loop counter is ONLY here for fake data,….do not use this syntax for production code */
    begin

          select @currentTVName = 'TV:     '+ convert(varchar(24) , @counter)

          INSERT into dbo.Television ( TelevisionName , TelevisionKey ) values ( @currentTVName , @counter)

          select @counter = @counter - 1      
    end


    select count(*) as TV_Total_COUNT from dbo.Television 

    /*
    –Does not Work!
    Update TOP (10) dbo.Television
          Set IsCheckedOut = 1
    FROM
          dbo.Television tv
    ORDER BY tv.TelevisionKey
    */
    declare @AuditTrail table ( TelevisionUUID uniqueidentifier , OldIsCheckedOut bit , NewIsCheckedOut bit )

    ;
    WITH cte1 AS       
     (  SELECT 
          TOP (@TopSize) 

       TelevisionUUID , /* <<Note, the columns here must be available to the output */
       IsCheckedOut        
          FROM   
                dbo.Television tv      
        WITH ( UPDLOCK, READPAST , ROWLOCK ) /*  <<Optional Hints, but helps with concurrency issues   */
          WHERE  
                IsCheckedOut = 0              
          ORDER BY
                tv.TelevisionKey DESC        
    )
    UPDATE cte1
          SET  IsCheckedOut = 1
    output inserted.TelevisionUUID , deleted.IsCheckedOut , inserted.IsCheckedOut into @AuditTrail ( TelevisionUUID , OldIsCheckedOut , NewIsCheckedOut )
    ;
    print ''
    print 'Newly Checked Out Items'
    select * from dbo.Television tv where tv.IsCheckedOut <> 0

    print 'Output AuditTrail'
    select * from @AuditTrail
    print 'Not checked out items'
    select count(*) as TVCOUNTIsNOTCheckedOut from dbo.Television tv where tv.IsCheckedOut = 0
于 2013-05-28T17:19:09.953 に答える