SQL: Актуализиране на всички избрани редове

В следния код. Само един от изразите 'Select' ще бъде изпълнен в даден момент. Искам да мога да актуализирам „Състоянието“ на всеки от избраните редове, както и да върна данните. Това основно предотвратява извличането на едни и същи записи по време на обработка в задната част.

Благодаря!

-- Insert statements for procedure here
if(@BatchSize > -1 and @Priority > -1)
begin
    Select TOP(@BatchSize) *,ID 
    From CompingQueue 
    Where PriorityLevel=@Priority 
       and Status=35 
    order by PriorityLevel asc;
end
if(@BatchSize = -1 and @Priority = -1)
begin
    Select * From CompingQueue 
    Where Status=35 
    order by PriorityLevel asc;
end

if(@BatchSize = -1 and @Priority > -1)
begin
   Select * From CompingQueue 
   WHEre PriorityLevel=@Priority 
     and Status=35     
   order by PriorityLevel asc;
end
if(@BatchSize > -1 and @Priority = -1)
begin
    Select TOP(@BatchSize) * 
    From CompingQueue 
    Where Status=35 
    order by PriorityLevel asc;
end
--update CompingQueue set Status = 2 where ID=
-- Set the Status Flag for each job

КРАЙ


person Brad Berdine    schedule 22.03.2013    source източник


Отговори (5)


Бих използвал DECLARE @tblResults TABLE (...). Вмъкнете редовете с SELECT в променливата на таблицата. Изпълнява свързване от изходната таблица към променливата на таблицата в PK, като използва това присъединяване като клауза в оператор UPDATE, след което връща променливата като резултат от query/proc/func.

person Jake H    schedule 22.03.2013
comment
Дори не е необходимо да съхранявате всички редове в @tblResults, можете просто да съхранявате първичните ключове. - person Tom Page; 22.08.2014

Единият вариант е просто да UPDATE таблицата и да използвате OUTPUT за съхраняване на актуализираните редове в променлива на таблица. След това можете да SELECT или да обработите допълнително данните в променливата на таблицата.

Има пример в документацията.

person Pondlife    schedule 22.03.2013

Искате клаузата OUTPUT.

http://msdn.microsoft.com/en-us/library/ms177564.aspx

Звучи сякаш искаш нещо подобно

UPDATE c
SET somestuff = something
OUTPUT DELETED.*
FROM CompingQueue c
WHERE someotherstuff

Или, ако искате данните след актуализацията, използвайте INSERTED.* вместо DELETED.*.

person Atario    schedule 22.03.2013

Какво ще кажете да ги направите всички наведнъж по този начин:

Declare @NumRecs int
if @BatchSize > -1 Set @NumRecs = @BatchSize 
else Select @NumRecs = Count(*) From CompingQueue 
-- --------------------------
Declare @Ids table (id int primary key not null)
Insert @Ids(id)
Select top(@numRecs) id 
From CompingQueue 
Where Status=35 
   And PriorityLevel = Case 
      When @Priority > -1 Then @Priority 
      Else PriorityLevel End
Order by PriorityLevel asc;

 Select * From CompingQueue 
 Where Id In (Select id from @Ids);

 Update CompingQueue Set
    status = 2
 Where Id In (Select id from @Ids);
person Charles Bretana    schedule 22.03.2013

SQL CTE ще ви помогне за вашия случай. Опитвате се да избегнете проблема с паралелността, защото множество процеси може да получат едни и същи записи за актуализиране. И във вашата заявка имате най-добрата партида, така че директно актуализирайте... изходът може би не е най-добрият избор. CTE + xlock, rowlock ще бъде по-добър избор


;with Update_batch 
as 
(
  select top 10 * from compingqueue With (xlock, rowlock)
  order by PriorityLevel desc
)
update Update_batch
set ....=....
Можете да третирате CTE като изглед в движение, с (xlock, rowlock), когато са избрани редове, (xlock, rowlock)ще бъде поставен на реда, което ще гарантира, че други процеси дори не могат да получат същите редове.

person ljh    schedule 22.03.2013