2013-12-05 7 views
4

Я хочу скопировать записи из одной таблицы в другую. Выполняя это, я хочу установить флаг этих записей, которые я копирую.Обновление во время копирования записей

Это, как я хотел бы сделать это (упрощенный):

BEGIN TRANSACTION copyTran 

    insert into destination_table (name) 
    select top 100 name 
    from source_table WITH (TABLOCKX) 
    order by id 

    update source_table 
    set copy_flag = 1 
    where id in (select top 100 id from source_table order by id) 

COMMIT TRANSACTION copyTran 

Есть ли более простой способ?

ответ

4

Используя OUTPUT положение можно варить до одного UPDATE заявления

UPDATE source_table 
    SET copy_flag = 1 
OUTPUT inserted.name 
    INTO destination_table(name) 
WHERE id IN 
(
    SELECT TOP 100 id 
    FROM source_table 
    ORDER BY id 
) 

Примечание: Теперь испытания. Должно работать нормально.

+1

Это потрясающе! –

1

Проблема с вашим запросом заключается в том, что вы можете получать разные записи в своем UPDATE, если кто-то вставляет некоторые данные во время выполнения вашего запроса. Использовать ключевое слово INSERTED.

Declare @temp TABLE (Id integer); 

INSERT INTO destination_table (name) 
    OUTPUT INSERTED.Id into @temp 
SELECT TOP 100 name 
FROM source_table 
ORDER BY id 

UPDATE source_table 
SET copy_flag = 1 
WHERE Id IN (SELECT Id FROM @temp) 
+0

Исходный запрос был заключен в транзакцию, поэтому изолирован и исправлен. – Twinkles

+2

Операции @Twinkles не гарантируют сериализуемость по умолчанию. Это было неправильно. – usr

+0

Я думаю, что существует больше потенциальных проблем, связанных с этим решением, не находящимся в транзакции. – Twinkles

0

Я думаю, что вы могли бы использовать временную таблицу, в которой вы будете хранить 100 лучших идентификаторами из таблицы источника, после того, как приказал им. Таким образом, вы избежите выполнения инструкции select в разделе where update для каждого идентификатора.

BEGIN TRANSACTION copyTran 

    insert into destination_table (name) 
    select top 100 name 
    from source_table 
    order by id 

    declare @Ids TABLE(id int) 
    @Ids = (select top 100 id from source_table order by id) 

    update source_table 
    set copy_flag = 1 
    where id in (SELECT * FROM @Ids) 

COMMIT TRANSACTION copyTran 
Смежные вопросы