Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 В Merge можно для одного условия указать несколько инструкций?  [new]
DaniilSeryi
Member

Откуда:
Сообщений: 1741
То есть есть ситуация, когда в случае с
WHEN MATCHED and...
надо сделать update старой записи и инсерт новой. Как это лучше сделать? Просьба пример.
Можно, конечно, два Merge один за другим, но как-то этот вариант мне не нравится.
18 июл 13, 15:22    [14584452]     Ответить | Цитировать Сообщить модератору
 Re: В Merge можно для одного условия указать несколько инструкций?  [new]
Добрый Э - Эх
Guest
Странный ты. Если строка "matched", то какая же она "новая"? Старая она, нужно её апдейтить. Новые строки пойдут в секции not matched. Вот там и инсерть...
18 июл 13, 15:26    [14584495]     Ответить | Цитировать Сообщить модератору
 Re: В Merge можно для одного условия указать несколько инструкций?  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74925
автор
Можно, конечно, два Merge один за другим,


UPDATE и INSERT друг за другом.
18 июл 13, 15:27    [14584507]     Ответить | Цитировать Сообщить модератору
 Re: В Merge можно для одного условия указать несколько инструкций?  [new]
Cygapb-007
Member

Откуда:
Сообщений: 1677
DaniilSeryi
надо сделать update старой записи и инсерт новой
Не это? UPDATE...OUTPUT...INTO...
18 июл 13, 15:53    [14584708]     Ответить | Цитировать Сообщить модератору
 Re: В Merge можно для одного условия указать несколько инструкций?  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Можно несколько инструкций, но с разными условиями фильтров. Почитайте же всётаки доку.

А Merge это набор волшебных звуков, практически заклинание "сделать мне хорошо".
Но почему-то гугл транслейт переводит Merge как "слияние". Странно, да?
18 июл 13, 15:54    [14584713]     Ответить | Цитировать Сообщить модератору
 Re: В Merge можно для одного условия указать несколько инструкций?  [new]
Cygapb-007
Member

Откуда:
Сообщений: 1677
Mnior,
а как понять многоточие в доке? Не пользовался, но интересно...
MERGE (Transact-SQL)
[ WHEN MATCHED [ AND <clause_search_condition> ]
THEN <merge_matched> ] [ ...n ]
18 июл 13, 16:01    [14584752]     Ответить | Цитировать Сообщить модератору
 Re: В Merge можно для одного условия указать несколько инструкций?  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
Cygapb-007
Mnior,
а как понять многоточие в доке? Не пользовался, но интересно...
MERGE (Transact-SQL)
[ WHEN MATCHED [ AND <clause_search_condition> ]
THEN <merge_matched> ] [ ...n ]
Я - не Mnoir!
Но это намекает, что всё, что слева,
можно повторить произвольное число раз n в данном случае через пробел.
18 июл 13, 16:04    [14584784]     Ответить | Цитировать Сообщить модератору
 Re: В Merge можно для одного условия указать несколько инструкций?  [new]
PaulWist
Member

Откуда:
Сообщений: 2231
Cygapb-007
Mnior,
а как понять многоточие в доке? Не пользовался, но интересно...
MERGE (Transact-SQL)
[ WHEN MATCHED [ AND <clause_search_condition> ]
THEN <merge_matched> ] [ ...n ]


А в доке для какого сервера такое написано?

Для 2008 нет "n"

[ WITH <common_table_expression> [,...n] ]
MERGE 
        [ TOP ( expression ) [ PERCENT ] ] 
        [ INTO ] target_table [ WITH ( <merge_hint> ) ] [ [ AS ] table_alias ]
        USING <table_source> 
        ON <merge_search_condition>
        [ WHEN MATCHED [ AND <clause_search_condition> ]
            THEN <merge_matched> ]
       [ WHEN NOT MATCHED [ BY TARGET ] [ AND <clause_search_condition> ]
            THEN <merge_not_matched> ]
        [ WHEN NOT MATCHED BY SOURCE [ AND <clause_search_condition> ]
            THEN <merge_matched> ]
        [ <output_clause> ]
        [ OPTION ( <query_hint> [ ,...n ] ) ]   
18 июл 13, 16:20    [14584969]     Ответить | Цитировать Сообщить модератору
 Re: В Merge можно для одного условия указать несколько инструкций?  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
PaulWist,

А тут есть, однако: http://msdn.microsoft.com/ru-ru/library/bb510625(v=sql.100).aspx
18 июл 13, 16:25    [14585020]     Ответить | Цитировать Сообщить модератору
 Re: В Merge можно для одного условия указать несколько инструкций?  [new]
Гость333
Member

Откуда:
Сообщений: 3683
iap
Cygapb-007
Mnior,
а как понять многоточие в доке? Не пользовался, но интересно...пропущено...
Я - не Mnoir!
Но это намекает, что всё, что слева,
можно повторить произвольное число раз n в данном случае через пробел.

Произвольное — енто вряд ли...
BOL -> MERGE
WHEN MATCHED THEN <merge_matched>
Указывается, что все строки target_table, которые соответствуют строкам, возвращенным <table_source> ON <merge_search_condition>, и удовлетворяют дополнительным условиям поиска, обновляются или удаляются в соответствии с предложением <merge_matched>.

Инструкция MERGE может иметь не больше двух предложений WHEN MATCHED. Если указаны два предложения, первое предложение должно сопровождаться предложением AND <search_condition>. Для любой строки второе предложение WHEN MATCHED применяется только в тех случаях, когда не применяется первое. Если имеются два предложения WHEN MATCHED, одно должно указывать действие UPDATE, а другое — действие DELETE. Если действие UPDATE указано в предложении <merge_matched> и более одной строки в <table_source>соответствует строке в target_table на основе <merge_search_condition>, то SQL Server возвращает ошибку. Инструкцию MERGE нельзя использовать для обновления одной строки более одного раза, а также использовать для обновления и удаления одной и той же строки.
18 июл 13, 16:29    [14585059]     Ответить | Цитировать Сообщить модератору
 Re: В Merge можно для одного условия указать несколько инструкций?  [new]
PaulWist
Member

Откуда:
Сообщений: 2231
iap
PaulWist,

А тут есть, однако: http://msdn.microsoft.com/ru-ru/library/bb510625(v=sql.100).aspx


Действительно, ОДНАКО!

"Как тебя понять, Абдула" (с) Белое солнце пустыни
18 июл 13, 16:33    [14585088]     Ответить | Цитировать Сообщить модератору
 Re: В Merge можно для одного условия указать несколько инструкций?  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
Гость333
iap
пропущено...
Я - не Mnoir!
Но это намекает, что всё, что слева,
можно повторить произвольное число раз n в данном случае через пробел.

Произвольное — енто вряд ли...
BOL -> MERGE
WHEN MATCHED THEN <merge_matched>
Указывается, что все строки target_table, которые соответствуют строкам, возвращенным <table_source> ON <merge_search_condition>, и удовлетворяют дополнительным условиям поиска, обновляются или удаляются в соответствии с предложением <merge_matched>.

Инструкция MERGE может иметь не больше двух предложений WHEN MATCHED. Если указаны два предложения, первое предложение должно сопровождаться предложением AND <search_condition>. Для любой строки второе предложение WHEN MATCHED применяется только в тех случаях, когда не применяется первое. Если имеются два предложения WHEN MATCHED, одно должно указывать действие UPDATE, а другое — действие DELETE. Если действие UPDATE указано в предложении <merge_matched> и более одной строки в <table_source>соответствует строке в target_table на основе <merge_search_condition>, то SQL Server возвращает ошибку. Инструкцию MERGE нельзя использовать для обновления одной строки более одного раза, а также использовать для обновления и удаления одной и той же строки.
Это уже комментарии.
А сама запись [ ...n] означает "произвольное число n раз".
Ну, хорошо, "некоторое число n раз". Хотя, это уже неочевидно
18 июл 13, 16:38    [14585132]     Ответить | Цитировать Сообщить модератору
 Re: В Merge можно для одного условия указать несколько инструкций?  [new]
DaniilSeryi
Member

Откуда:
Сообщений: 1741
Если отвлечься от Merge - как бы Вы решили следующую задачу:

Приходят раз в месяц данные из другой таблицы.
Данные идут нарастающим итогом, то есть в первый раз пришли 100 строк, во второй раз придут эти же 100 строк + 50 новых, в третий - 150 + 40 новых... и т.д.

Если пришедшая строка - новая - её надо вставить;
если строка старая и не изменилась за отчётный период - с ней ничего не происходит;
если строка старая и изменилась - строку в нашей БД надо пометить как Changed, а пришедшую - записать;
если же строка в таблице-источнике была удалена - то у нас её надо пометить как Deleted.

Строки, помеченные как Changed или Deleted - в сверке с пришедшими не участвуют.

Проблема с "строка старая и изменилась".

Пока вариант - два Merge с одними и теми же наборами данных. Первый Merge метит изменившуюся строку как Changed, второй - вставляет в базу её новую версию.
18 июл 13, 18:37    [14585878]     Ответить | Цитировать Сообщить модератору
 Re: В Merge можно для одного условия указать несколько инструкций?  [new]
Гость333
Member

Откуда:
Сообщений: 3683
DaniilSeryi
Если пришедшая строка - новая - её надо вставить;
если строка старая и не изменилась за отчётный период - с ней ничего не происходит;
если строка старая и изменилась - строку в нашей БД надо пометить как Changed, а пришедшую - записать;
если же строка в таблице-источнике была удалена - то у нас её надо пометить как Deleted.

Можно использовать новую возможность MSSQL 2008 — в команде INSERT в качестве источника данных можно использовать вывод из OUTPUT-кляузы DML-команды.
Правда, на таблицу-приёмник наложены жёсткие ограничения:
BOL -> INSERT
If <dml_table_source> is specified, the target of the outer INSERT statement must meet the following restrictions:
  • It must be a base table, not a view.
  • It cannot be a remote table.
  • It cannot have any triggers defined on it.
  • It cannot participate in any primary key-foreign key relationships.
  • It cannot participate in merge replication or updatable subscriptions for transactional replication.
    The compatibility level of the database must be set to 100 or higher.

  • Тогда решение вашей задачи выглядит примерно так:
    declare @OurTable table (id int not null, name varchar(100) not null, action varchar(20) default 'No action');
    insert @OurTable (id, name) values (1, 'Иванов'), (2, 'Петрова'), (3, 'Сидоров');
    
    declare @NewTable table (id int not null, name varchar(100) not null);
    insert @NewTable (id, name)
    values
       (1, 'Иванов'),   -- если строка старая и не изменилась за отчётный период - с ней ничего не происходит
       (2, 'Кузьмина'), -- если строка старая и изменилась - строку в нашей БД надо пометить как Changed, а пришедшую - записать;
       -- Где 3? Нет 3! -- если же строка в таблице-источнике была удалена - то у нас её надо пометить как Deleted.
       (4, 'Михайлов'); -- Если пришедшая строка - новая - её надо вставить;
    
    select * from @OurTable order by id;
    
    insert @OurTable (id, name, action)
    select t.id, t.name, 'Changed: new value'
    from
    (
      merge @OurTable as our
      using @NewTable as new
        on new.id = our.id
      when matched and new.name <> our.name
        then update set action = 'Changed'
      when not matched by target
        then insert (id, name, action)
             values (new.id, new.name, 'Inserted')
      when not matched by source
        then update set action = 'Deleted'
      output inserted.id, new.name, inserted.action
    ) t
    where t.action = 'Changed';
    
    select * from @OurTable order by id;
    

    Если из-за ограничений вставлять напрямую в таблицу-приёмник нельзя, то можно выгрузить данные сначала во временную таблицу, а уже из неё — в таблицу приёмник.
    (Собственно, я бы перекачивал через временную таблицу, даже если ограничений нет... ибо сейчас их нет, а потом запросто могут появиться.)
    19 июл 13, 09:31    [14587558]     Ответить | Цитировать Сообщить модератору
     Re: В Merge можно для одного условия указать несколько инструкций?  [new]
    Гость333
    Member

    Откуда:
    Сообщений: 3683
    Упустил ещё это условие:
    DaniilSeryi
    Строки, помеченные как Changed или Deleted - в сверке с пришедшими не участвуют.

    Ок, модификация небольшая:
    + Исправленный пример
    declare @OurTable table (id int not null, name varchar(100) not null, action varchar(20) not null);
    insert @OurTable (id, name, action) values (1, 'Иванов', 'No action'), (2, 'Васильева', 'Deleted'), (2, 'Петрова', 'No action'), (3, 'Сидоров', 'No action'),
                     (0, 'Мистер X', 'Changed'), (-1, 'Мистер Y', 'Deleted'), (4, 'Мистер Z', 'Deleted');
    
    declare @NewTable table (id int not null, name varchar(100) not null);
    insert @NewTable (id, name)
    values
       (1, 'Иванов'),   -- если строка старая и не изменилась за отчётный период - с ней ничего не происходит
       (2, 'Кузьмина'), -- если строка старая и изменилась - строку в нашей БД надо пометить как Changed, а пришедшую - записать;
       -- Где 3? Нет 3! -- если же строка в таблице-источнике была удалена - то у нас её надо пометить как Deleted.
       (4, 'Михайлов'); -- Если пришедшая строка - новая - её надо вставить;
    
    select * from @OurTable order by id;
    
    insert @OurTable (id, name, action)
    select t.id, t.name, 'Changed: new value'
    from
    (
      merge @OurTable as our
      using @NewTable as new
        on new.id = our.id and our.action not in ('Changed', 'Deleted')
      when matched and new.name <> our.name
        then update set action = 'Changed'
      when not matched by target
        then insert (id, name, action)
             values (new.id, new.name, 'Inserted')
      when not matched by source and our.action not in ('Changed', 'Deleted')
        then update set action = 'Deleted'
      output inserted.id, new.name, inserted.action
    ) t
    where t.action = 'Changed';
    
    select * from @OurTable order by id;
    
    19 июл 13, 09:41    [14587613]     Ответить | Цитировать Сообщить модератору
     Re: В Merge можно для одного условия указать несколько инструкций?  [new]
    Cygapb-007
    Member

    Откуда:
    Сообщений: 1677
    Гость333,

    только там возникают проблемы при повторных обновлениях - если, например, update @OurTable set name='Третьева' where id=2
    19 июл 13, 09:45    [14587644]     Ответить | Цитировать Сообщить модератору
     Re: В Merge можно для одного условия указать несколько инструкций?  [new]
    Cygapb-007
    Member

    Откуда:
    Сообщений: 1677
    а, пофиксено, увидел:)
    19 июл 13, 09:46    [14587652]     Ответить | Цитировать Сообщить модератору
    Все форумы / Microsoft SQL Server Ответить