Ms sql merge пример: Операция MERGE в языке Transact-SQL – описание и примеры | Info-Comp.ru

Содержание

Операция MERGE в языке Transact-SQL – описание и примеры | Info-Comp.ru

В языке Transact-SQL в одном ряду с такими операциями как INSERT (вставка), UPDATE (обновление), DELETE (удаление) стоит операция MERGE (слияние), которая в некоторых случаях может быть полезна, но некоторые почему-то о ней не знают и не пользуются ею, поэтому сегодня мы рассмотрим данную операцию и разберем примеры.

Начнем мы, конечно же, с небольшой теории.

Заметка! Начинающим рекомендую посмотреть мой видеокурс по T-SQL.

Что такое MERGE в T-SQL?

MERGE – операция в языке T-SQL, при которой происходит обновление, вставка или удаление данных в таблице на основе результатов соединения с данными другой таблицы или SQL запроса. Другими словами, с помощью MERGE можно осуществить слияние двух таблиц, т.е. синхронизировать их.

В операции MERGE происходит объединение по ключевому полю или полям основной таблицы (в которой и будут происходить все изменения) с соответствующими полями другой таблицы или результата запроса. В итоге если условие, по которому происходит объединение, истина (

WHEN MATCHED), то мы можем выполнить операции обновления или удаления, если условие не истина, т.е. отсутствуют данные (WHEN NOT MATCHED), то мы можем выполнить операцию вставки (INSERT добавление данных), также если в основной таблице присутствуют данные, которое отсутствуют в таблице (или результате запроса) источника (WHEN NOT MATCHED BY SOURCE), то мы можем выполнить обновление или удаление таких данных.

В дополнение к основным перечисленным выше условиям можно указывать «Дополнительные условия поиска», они указываются через ключевое слово AND.

Упрощённый синтаксис MERGE

  
        MERGE <Основная таблица>
                USING <Таблица или запрос источника> 
                ON <Условия объединения>
                [ WHEN MATCHED [ AND <Доп. условие> ]
                        THEN <UPDATE или DELETE>
                [ WHEN NOT MATCHED [ AND Доп. условие> ]
                        THEN <INSERT> ]
                [ WHEN NOT MATCHED BY SOURCE [ AND <Доп. условие> ]
                        THEN <UPDATE или DELETE> ] [ ...n ] 
                [ OUTPUT ]
        ;


Важные моменты при использовании MERGE:

  • В конце инструкции MERGE обязательно должна идти точка с запятой (;) иначе возникнет ошибка;
  • Должно быть, по крайней мере, одно условие MATCHED;
  • Операцию MERGE можно использовать совместно с CTE (обобщенным табличным выражением);
  • В инструкции MERGE можно использовать ключевое слово OUTPUT, для того чтобы посмотреть какие изменения были внесены. Для идентификации операции здесь в OUTPUT можно использовать переменную $action;
  • На все операции к основной таблице, которые предусмотрены в MERGE (удаления, вставки или обновления), действуют все ограничения, определенные для этой таблицы;
  • Функция @@ROWCOUNT, если ее использовать после инструкции MERGE, будет возвращать общее количество вставленных, обновленных и удаленных строк;
  • Для того чтобы использовать MERGE необходимо разрешение на INSERT, UPDATE или DELETE в основной таблице, и разрешение SELECT для таблицы источника;
  • При использовании MERGE необходимо учитывать, что все триггеры AFTER на INSERT, UPDATE или DELETE, определенные для целевой таблицы, будут запускаться.

А теперь переходим к практике. И для начала давайте определимся с исходными данными.

Исходные данные для примеров операции MERGE

У меня в качестве SQL сервера будет выступать Microsoft SQL Server 2016 Express. На нем есть тестовая база данных, в которой я создаю тестовые таблицы, например, с товарами:

TestTable – это у нас будет целевая таблица, т.е. та над которой мы будем производить все изменения, и TestTableDop – это таблица источник, т.е. данные в соответствии с чем, мы будем производить изменения.

Запрос для создания таблиц.

  
  --Целевая таблица
  CREATE TABLE dbo.TestTable(
        ProductId INT NOT NULL,
        ProductName VARCHAR(50) NULL,
        Summa MONEY NULL,
  CONSTRAINT PK_TestTable PRIMARY KEY CLUSTERED (ProductId ASC)
  )
  --Таблица источник
  CREATE TABLE dbo.TestTableDop(
        ProductId INT NOT NULL,
        ProductName VARCHAR(50) NULL,
        Summa MONEY NULL,
  CONSTRAINT PK_TestTableDop PRIMARY KEY CLUSTERED (ProductId ASC)
  )


Далее я их наполняю тестовыми данными.

   
        --Добавляем данные в основную таблицу
        INSERT INTO dbo.TestTable
                           (ProductId,ProductName,Summa)
                 VALUES
                           (1, 'Компьютер', 0)
        GO
        INSERT INTO dbo.TestTable
                           (ProductId,ProductName,Summa)
                 VALUES
                           (2, 'Принтер', 0)
        GO
        INSERT INTO dbo.TestTable
                           (ProductId,ProductName,Summa)
                 VALUES
        (3, 'Монитор', 0)
        GO
        --Добавляем данные в таблицу источника
        INSERT INTO dbo.TestTableDop
                           (ProductId,ProductName,Summa)
                 VALUES
                           (1, 'Компьютер', 500)
        GO
        INSERT INTO dbo.TestTableDop
                           (ProductId,ProductName,Summa)
                 VALUES
                           (2, 'Принтер', 300)
        GO
        INSERT INTO dbo.TestTableDop
                           (ProductId,ProductName,Summa)
                 VALUES
                           (4, 'Монитор', 400)
        GO


Посмотрим на эти данные.

  
  SELECT * FROM dbo.TestTable

  SELECT * FROM dbo.TestTableDop


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

Пример 1 – обновление и добавление данных с помощью MERGE

Это, наверное, классический вариант использования MERGE, когда мы по условию объединения обновляем данные, а если таких данных нет, то добавляем их. Для наглядности в конце инструкции MERGE я укажу ключевое слово OUTPUT, для того чтобы посмотреть какие именно изменения мы произвели, а также сделаю выборку итоговых данных.

   
        MERGE dbo.TestTable AS T_Base --Целевая таблица
        USING dbo.TestTableDop AS T_Source --Таблица источник
        ON (T_Base.ProductId = T_Source.ProductId) --Условие объединения
        WHEN MATCHED THEN --Если истина (UPDATE)
                 UPDATE SET ProductName = T_Source.ProductName, Summa = T_Source.Summa
        WHEN NOT MATCHED THEN --Если НЕ истина (INSERT)
                 INSERT (ProductId, ProductName, Summa) 
                 VALUES (T_Source.ProductId, T_Source.ProductName, T_Source.Summa)
        --Посмотрим, что мы сделали
        OUTPUT $action AS [Операция], Inserted.ProductId,
                   Inserted.ProductName AS ProductNameNEW,
                   Inserted.Summa AS SummaNEW, 
                   Deleted.ProductName AS ProductNameOLD, 
                   Deleted.Summa AS SummaOLD; --Не забываем про точку с запятой
        --Итоговый результат
        SELECT * FROM dbo.TestTable
        SELECT * FROM dbo.TestTableDop


Мы видим, что у нас было две операции UPDATE и одна INSERT. Так оно и есть, две строки из таблицы TestTable соответствуют двум строкам в таблице TestTableDop, т.е. у них один и тот же ProductId, у данных строк в таблице TestTable мы обновили поля ProductName и Summa. При этом в таблице TestTableDop есть строка, которая отсутствует в TestTable, поэтому мы ее и добавили через INSERT.

Пример 2 – синхронизация таблиц с помощью MERGE

Теперь, допустим, нам нужно синхронизировать таблицу TestTable с таблицей TestTableDop, для этого мы добавим еще одно условие WHEN NOT MATCHED BY SOURCE, суть его в том, что мы удалим строки, которые есть в TestTable, но нет в TestTableDOP. Но для начала, для того чтобы у нас все три условия отработали (в частности WHEN NOT MATCHED) давайте в таблице TestTable удалим строку, которую мы добавили в предыдущем примере. Также здесь я в качестве источника укажу запрос, чтобы Вы видели, как можно использовать запросы в качестве источника.

   
        --Удаление строки с ProductId = 4 
        --для того чтобы отработало условие WHEN NOT MATCHED
        DELETE dbo.TestTable WHERE ProductId = 4
        --Запрос MERGE для синхронизации таблиц
        MERGE dbo.TestTable AS T_Base --Целевая таблица
        --Запрос в качестве источника
        USING (SELECT ProductId, ProductName, Summa 
                   FROM dbo.TestTableDop) AS T_Source (ProductId, ProductName, Summa) 
        ON (T_Base.ProductId = T_Source.ProductId) --Условие объединения
        WHEN MATCHED THEN --Если истина (UPDATE)
                 UPDATE SET ProductName = T_Source.ProductName, Summa = T_Source.Summa
        WHEN NOT MATCHED THEN --Если НЕ истина (INSERT)
                 INSERT (ProductId, ProductName, Summa)
                 VALUES (T_Source.ProductId, T_Source.ProductName, T_Source.Summa)
         --Удаляем строки, если их нет в TestTableDOP
        WHEN NOT MATCHED BY SOURCE THEN
                 DELETE  
        --Посмотрим, что мы сделали
        OUTPUT $action AS [Операция], Inserted.ProductId, Inserted.ProductName AS ProductNameNEW,
                   Inserted.Summa AS SummaNEW,Deleted.ProductName AS ProductNameOLD, 
                   Deleted.Summa AS SummaOLD; --Не забываем про точку с запятой
        --Итоговый результат
        SELECT * FROM dbo.TestTable
        SELECT * FROM dbo.TestTableDop 


В итоге мы видим, что у нас таблицы содержат одинаковые данные. Для этого мы выполнили две операции UPDATE, одну INSERT и одну DELETE. При этом мы использовали всего одну инструкцию MERGE.

Пример 3 – операция MERGE с дополнительным условием

Сейчас давайте выполним запрос похожий на запрос, который мы использовали в примере 1, только добавим дополнительное условие на обновление данных, например, мы будем обновлять TestTable только в том случае, если поле Summa, в TestTableDop, содержит какие-нибудь данные (например, мы не хотим использовать некорректные значения для обновления

). Для того чтобы было видно, как отработало это условие, давайте предварительно очистим у одной строки в таблице TestTableDop поле Summa (поставим NULL).

   
        --Очищаем поле сумма у одной строки в TestTableDop
        UPDATE dbo. TestTableDop SET Summa = NULL 
        WHERE ProductId = 2
        --Запрос MERGE 
        MERGE dbo.TestTable AS T_Base --Целевая таблица
        USING dbo.TestTableDop AS T_Source --Таблица источник
        ON (T_Base.ProductId = T_Source.ProductId) --Условие объединения
        --Если истина + доп. условие отработало (UPDATE)
        WHEN MATCHED AND T_Source.Summa IS NOT NULL THEN
                 UPDATE SET ProductName = T_Source.ProductName, Summa = T_Source.Summa
        WHEN NOT MATCHED THEN --Если НЕ истина (INSERT)
                 INSERT (ProductId, ProductName, Summa)
                 VALUES (T_Source.ProductId, T_Source.ProductName, T_Source.Summa)
        --Посмотрим, что мы сделали
        OUTPUT $action AS [Операция], Inserted.ProductId,
                   Inserted.ProductName AS ProductNameNEW, 
                   Inserted.Summa AS SummaNEW, 
                   Deleted.ProductName AS ProductNameOLD, 
                   Deleted.Summa AS SummaOLD; --Не забываем про точку с запятой
        --Итоговый результат
        SELECT * FROM dbo.TestTable
        SELECT * FROM dbo.TestTableDop


В итоге у меня обновилось всего две строки, притом, что все три строки успешно выполнили условие объединения, но одна строка не обновилась, так как сработало дополнительное условие Summa IS NOT NULL, потому что поле Summa у строки с ProductId = 2, в таблице TestTableDop, не содержит никаких данных, т.е. NULL.

Заметка! Для комплексного изучения языка SQL и T-SQL рекомендую посмотреть мои видеокурсы по T-SQL, которые помогут Вам «с нуля» научиться работать с SQL и программировать на T-SQL в Microsoft SQL Server.

На этом у меня все, удачи!

Нравится8Не нравится

Объяснение оператора MERGE в SQL

Обязательное условие заявление MERGE
Оператор MERGE в SQL, как обсуждалось ранее в предыдущем посте , представляет собой комбинацию трех операторов INSERT , DELETE и UPDATE . Таким образом, если есть таблица источника и таблица назначения , которые должны быть объединены, то с помощью оператора MERGE все три операции (INSERT, UPDATE, DELETE) могут выполняться одновременно.

Простой пример пояснит использование MERGE Statement.
Пример:

Предположим, есть две таблицы:

  1. PRODUCT_LIST — таблица, содержащая текущие сведения о продуктах, доступных с полями P_ID, P_NAME и P_PRICE, соответствующими идентификатору, названию и цене каждого продукта.
  2. UPDATED_LIST — таблица, содержащая новые сведения о продуктах, доступные в полях P_ID, P_NAME и P_PRICE, соответствующих идентификатору, названию и цене каждого продукта.

Задача состоит в том, чтобы обновить информацию о продуктах в PRODUCT_LIST в соответствии с UPDATED_LIST.

Решение
Теперь, чтобы объяснить этот пример лучше, давайте разделим пример на шаги.

  • Шаг 1: Распознать ЦЕЛЬ и таблицу ИСТОЧНИК
    Таким образом, в этом примере, поскольку его просят обновить продукты в PRODUCT_LIST согласно UPDATED_LIST, следовательно, PRODUCT_LIST будет действовать как TARGET, а UPDATED_LIST будет действовать как таблица SOURCE.

  • Шаг 2: Распознать выполняемые операции.
    Теперь, как видно, между TARGET и таблицей SOURCE есть три несоответствия:
    1. Стоимость КОФЕ в ЦЕЛЕ составляет 15.00, а в ИСТОЧНИКЕ — 25.00.
            PRODUCT_LIST
      102     COFFEE    15.00
      
            UPDATED_LIST
      102     COFFEE    25.00
      
    2. В SOURCE нет продукта BISCUIT, но он находится в TARGET
            PRODUCT_LIST
      103     BISCUIT   20.00
      
    3. В TARGET нет продукта CHIPS, но он находится в SOURCE
            UPDATED_LIST
      104     CHIPS     22.00
      

    Следовательно, в TARGET необходимо выполнить три операции в соответствии с вышеуказанными несоответствиями. Они есть:

    1. UDPATE операция
      102     COFFEE    25.00
      
    2. УДАЛИТЬ операцию
      103     BISCUIT   20.00
      
    3. Операция вставки
      104     CHIPS     22.00
      
  • Шаг 3: Напишите SQL-запрос.

    Note: Refer this post for the syntax of MERGE statement.

    SQL-запрос для выполнения вышеупомянутых операций с помощью оператора MERGE :

    /* Selecting the Target and the Source */

    MERGE PRODUCT_LIST AS TARGET

        USING UPDATE_LIST AS SOURCE 

      

        /* 1. Performing the UPDATE operation */

      

        /* If the P_ID is same, 

           check for change in P_NAME or P_PRICE */

        ON (TARGET.P_ID = SOURCE.P_ID)

        WHEN MATCHED 

             AND TARGET.P_NAME <> SOURCE.P_NAME 

             OR TARGET.P_PRICE <> SOURCE.P_PRICE

      

        /* Update the records in TARGET */

        THEN UPDATE 

             SET TARGET.P_NAME = SOURCE.P_NAME,

             TARGET.P_PRICE = SOURCE.P_PRICE

           

        /* 2. Performing the INSERT operation */

      

        /* When no records are matched with TARGET table 

           Then insert the records in the target table */

        WHEN NOT MATCHED BY TARGET 

        THEN INSERT (P_ID, P_NAME, P_PRICE)          

             VALUES (SOURCE.P_ID, SOURCE.P_NAME, SOURCE.P_PRICE)

      

        /* 3. Performing the DELETE operation */

      

        /* When no records are matched with SOURCE table 

           Then delete the records from the target table */

        WHEN NOT MATCHED BY SOURCE 

        THEN DELETE

      

    /* END OF MERGE */

  • Выход:

       PRODUCT_LIST
P_ID    P_NAME    P_PRICE
101     TEA       10.00 
102     COFFEE    25.00
104     CHIPS     22.00

Таким образом, таким образом все мы можем выполнить все эти три основных оператора в SQL вместе с помощью оператора MERGE.

Примечание. Любое имя, отличное от target и source, может использоваться в синтаксисе MERGE. Они используются только для того, чтобы дать вам лучшее объяснение.

Эта статья предоставлена Dimpy Varshni . Если вы как GeeksforGeeks и хотели бы внести свой вклад, вы также можете написать статью с помощью contribute.geeksforgeeks.org или по почте статьи [email protected] Смотрите свою статью, появляющуюся на главной странице GeeksforGeeks, и помогите другим вундеркиндам.

Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное, или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Рекомендуемые посты:

Объяснение оператора MERGE в SQL

0.00 (0%) 0 votes

Инструкция MERGE | sql-oracle.ru

  • Выполняется операция UPDATE, если строки существуют, и операция INSERT, если это новая строка:

    • исключает необходимость в отдельных обновлениях;

    • повышается производительность и простота использования;

    • удобна в приложениях хранилища данных.

Сервером Oracle поддерживается инструкция MERGE для операций INSERT, UPDATE и DELETE. Используя эту инструкцию, можно обновить, вставить или удалить строку по условию в таблице, таким образом исключая необходимость применения нескольких инструкций DML. Решение о выполнении обновления, вставки или удаления в целевой таблице основывается на условии в предложении ON.

Необходимо иметь объектные привилегии INSERT и UPDATE на целевую таблицу и объектную привилегию SELECT на исходную таблицу. Чтобы задать предложение DELETE для merge_update_clause, необходимо также обладать объектной привилегией DELETE на целевую таблицу.

Инструкция MERGE является детерминированной. Одну и ту же строку целевой таблицы невозможно обновить несколько раз в одной и той же инструкции MERGE.

Альтернативный подход состоит в использовании циклов PL/SQL и нескольких инструкций DML. Однако инструкцию MERGE удобно использовать и проще выразить в виде одиночной инструкции SQL.

Инструкция MERGE удобна в ряде приложений хранилища данных. Например, в приложении хранилища данных иногда возникает необходимость в работе с данными, поступающими из нескольких источников, часть из которых может быть дубликатами. Инструкция MERGE позволяет добавлять и изменять строки по определенному условию.

Синтаксис инструкции MERGE

Используя инструкцию MERGE, можно по определенному условию вставлять, обновлять и удалять строки в таблице.

Объединение строк

Используя инструкцию MERGE, можно обновлять существующие строки и вставлять новые строки по определенному условию. Применяя инструкцию MERGE, можно удалить устаревшие строки одновременно с обновлением строк в таблице. Чтобы сделать это, в синтаксис инструк- ции MERGE включите предложение DELETE со своим собственным предложением WHERE.

Элементы синтаксиса:

  • Предложение INTO — задает целевую таблицу, которая обновляется или в которую выполняется вставка.

  • Предложение USING — идентифицирует источник обновляемых или вставляемых данных; может быть таблицей, представлением или подзапросом.

  • Предложение ON — условие, по которому операция MERGE выполняет обновление или вставку.

  • WHEN MATCHED | WHEN NOT MATCHED — предписывает серверу, как реагировать на результаты условия объединения

Более подробно изложено в документации Oracle Database 11g SQL Reference (Справочник по SQL для базы данных Oracle 11g).

Далее: Функции TO_YMINTERVAL и TO_DSINTERVAL

Тонкости благополучного git-merge / Хабр

Вступительное слово

Считается, что «киллер фичей» СКВ Git является легковесное ветвление. Я ощутил это преимущество в полной мере, ведь я перешел на Git с SVN, где ветвление было достаточно дорогим процессом: для создания ветки нужно было скопировать весь рабочий каталог. В Git все проще: создание ветки подразумевает лишь создание нового указателя на определенный коммит в папке .git/refs/heads, который является файлом с 40 байтами текста, хешем коммита.

Основными командами пользовательского уровня для ветвления в Git являются git-branch, git-checkout, git-rebase, git-log и, конечно же, git-merge. Для себя я считаю git-merge зоной наибольшей ответственности, точкой огромной магической энергии и больших возможностей. Но это достаточно сложная команда, и даже достаточно длительный опыт работы с Git порой бывает недостаточным для освоение всех ее тонкостей и умения применить ее наиболее эффективно в какой-либо нестандартной ситуации.

Попробуем же разобраться в тонкостях git-merge и приручить эту великую магию.

Здесь я хочу рассмотреть только случай благополучного слияния, под которым я понимаю слияние без конфликтов. Обработка и разрешение конфликтов — отдельная интересная тема, достойная отдельной статьи. Я очень рекомендую так же ознакомиться со статьей Внутреннее устройство Git: хранение данных и merge, содержащей много важной информации, на которую я опираюсь.

Анатомия команды

Если верить мануалу, команда имеет следующий синтаксис:

git merge [-n] [--stat] [--no-commit] [--squash] [--[no-]edit]
[-s <strategy>] [-X <strategy-option>]
[--[no-]rerere-autoupdate] [-m <msg>] [<commit>...]
git merge <msg> HEAD <commit>...
git merge --abort


По большому счету, в Git есть два вида слияния: перемотка (fast-forward merge) и «истинное» слияние (true merge). Рассмотрим несколько примеров обоих случаев.

«Истинное» слияние (true merge)

Мы отклоняемся от ветки master, чтобы внести несколько багов улучшений. История коммитов у нас получилась следующая:

master: A - B - C - D
                 \
feature:          X - Y


Выполним на ветке master git merge feature:

master: A - B - C - D - (M)
                 \      /
feature:          X - Y


Это наиболее частый паттерн слияния. В данном случае в ветке master создается новый коммит (M), который будет ссылаться на двух родителей: коммит D и коммит Y; а указатель master установится на коммит (M). Таким образом Git будет понимать, какие изменения соответствуют коммиту (M) и какой коммит последний в ветке master. Обычно коммит слияния делается с сообщением вроде «Merge branch ‘feature’», но можно определить и свое сообщение коммита с помощью ключа -m.

Посмотрим историю коммитов в тестовом репозитории, который я создал специально для этого случая:

$ git log --oneline
92384bd (M)
bceb5a4 D
5dce5b1 Y
76f13e7 X
d1920dc C
3a5c217 B
844af94 A


А теперь посмотрим информацию о коммите (M):

$ git cat-file -p 92384bd
tree 2b5c78f9086384bd86a2ab9d00c7e41a56f01d04
parent bceb5a4ad88e80467404473b94c3e0758dd8e0be
parent 5dce5b1edef64bd0d4e1039061a77be4d7182678
author Andre <[email protected]> 1380475972 +0400
committer Andre <[email protected]> 1380475972 +0400

(M)


Мы видим двух родителей, объект-дерево, соответствующее данному состоянию файлов репозитория, а так же информацию о том, кто виновен в коммите.

Посмотрим, куда ссылается указатель master:

$ cat .git/refs/heads/master
92384bd77304c09b81dcc4485da165923b96ed5f


Действительно, он теперь передвинут на коммит (M).

Squash и no-commit

Но что делать, если за содержимое ветки feature вас могут побить? К примеру, улучшение было небольшим, и вполне могло уместиться в один логичный коммит, но так вышло, что посреди работы вам было нужно убегать на электричку, а продолжать уже дома? В таком случае есть два выхода: экспорт репозитория с последующим импортом на другой машине, либо (особенно когда до электрички 10 минут, а до вокзала около километра) — сделать push origin feature.

Заливать незаконченные коммиты в основную ветку плохо, и с этим нужно что-то делать. Одним из способов, и, пожалуй самым простым, является опция --squash.

git merge feature --squash объединит изменения всех коммитов ветки feature, перенесет их в ветку master и добавит в индекс. При этом коммит слияния не будет создан, вам нужно будет сделать его вручную.

Такого же поведения без параметра squash можно добиться, передав при слиянии параметр --no-commit.

В случае применения такого слияния коммиты ветки feature не будут включены в нашу историю, но коммит Sq будет содержать все их изменения:

master: A - B - C - D - Sq
                 \ 
feature:          X - Y

Позже, в случае выполнения «классического» git merge feature можно исправить это. Тогда история примет следующий вид:

master: A - B - C - D - Sq - (M)
                 \           /
feature:          X    -    Y

В случае, если вы выполнили слияние без коммита, а потом поняли, что совершили фатальную ошибку, все можно отменить простой командой: git merge --abort. Эта же команда может быть применена, если во время слияния произошли конфликты, а разрешать их в данный момент не хочется.

Перемотка (fast-forward merge)

Рассмотрим другой случай истории коммитов:

master: A - B - C
                 \
feature:          X - Y


Все как и в прошлый раз, но теперь в ветке master нет коммитов после ответвления. В этом случае происходит слияние fast-forward (перемотка). В этом случае отсутствует коммит слияния, указатель (ветка) master просто устанавливается на коммит Y, туда же указывает и ветка feature:

master, feature: A - B - C - X - Y


Чтобы предотвратить перемотку, можно использовать параметр --no-ff.
В случае, если мы выполним git merge feature --no-ff -m '(M)', мы получим уже такую картину:

master: A - B - C   -  (M)
                 \     /
feature:          X - Y


Если же для нас единственным приемлемым поведением является fast-forward, мы можем указать опцию --ff-only. В этом случае, если к слиянию не применима перемотка, будет выведено сообщение о невозможности совершить слияние. Именно так было бы, если бы мы добавили опцию --ff-only в самом первом примере, где после ответвления feature в ветке master был сделано коммит C.

Можно добавить, что при выполнении git pull origin branch_name применяется как раз что-то вроде --ff-only. То есть, в случае, если при слиянии с веткой origin/branch_name не приемлема перемотка, операция отменяется и выводится сообщении о невозможности выполнения.

Стратегии слияния

У команды git-merge есть интересный параметр, --strategy, стратегия. Git поддерживает следующие стратегии слияния:
  • resolve
  • recursive
  • ours
  • octopus
  • subtree
Стратегия resolve

Стратегия resolve — классическое трехсторонее слияние (three-way merge). Стандартный алгоритм трехстороннего слияния применяется для двух файлов с общим предком. Условно этот алгоритм можно представить в виде следующих шагов:
  1. поиск общего предка,
  2. поиск блоков, изменившихся в обеих версиях относительно общего предка,
  3. записываются блоки, оставшиеся без изменения,
  4. блоки, изменившиеся только в одном из потомков, записываются как измененные,
  5. блоки, изменившиеся в обеих версиях, записываются только если изменения идентичны, в ином случае объявляется конфликт, разрешение которого предоставляется пользователю.

Эта стратегия имеет один недостаток: в качестве общего предка двух веток всегда выбирается наиболее ранний общий коммит. Для случая из нашего первого примера это не страшно, можно смело применять git merge feature -s resolve, и результат будет ожидаемым:

master: A - B - C - D - (M)
                 \      /
feature:          X - Y


Здесь C — общий коммит двух веток, дерево файлов, соответствующее этому коммиту, принимается за общего предка. Анализируются изменения, произведенные в ветках master и feature со времен этого коммита, после чего для коммита (M) создается новая версия дерева файлов в соответствии с пунктами 4 и 5 нашего условного алгоритма.

В каком же случае проявляется недостаток стратегии resolve? Он проявляется в том случае, если для коммита (M) нам пришлось разрешить конфликты, после чего мы продолжили разработку и еще раз хотим выполнить git merge feature -s resolve. В этом случае в качестве общего предка снова будет использован коммит C, и конфликты произойдут снова и будут нуждаться в нашем вмешательстве.

Стратегия recursive

Данная стратегия решает проблемы стратегии resolve. Она так же реализует трехстороннее слияние, но в качестве предка используется не реальный, а «виртуальный» предок, который конструируется по следующему условному алгоритму:
  1. проводится поиск всех кандидатов на общего предка,
  2. по цепочке проводится слияние кандидатов, в результате чего появляется новый «виртуальный» предок, причем более свежие коммиты имеют более высокий приоритет, что позволяет избежать повторного проявления конфликтов.

Результат этого действия принимается за общего предка и проводится трехсторонее слияние.

Для иллюстрации этой стратегии позаимствуем пример из статьи Merge recursive strategy из блога «The plasticscm blog»:

Итак, у нас есть две ветки: main и task001. И так вышло, что наши разработчики знают толк в извращениях: они слили коммит 15 из ветки main с коммитом 12 из ветки task001, а так же коммит 16 с коммитом 11. Когда нам понадобилось слить ветки, оказалось, что поиск реального предка — дело неблагодарное, но стратегия recursive с ее конструированием «виртуального» предка нам поможет. В результате мы получим следующую картину:

Стратегия recursive имеет множество опций, которые передаются команде git-merge с помощью ключа -X:

  • ours и theirs
    Используются для автоматического разрешения конфликтов. Ours — предпочитать «нашу» версию, версию «dst», theirs — предпочитать «их» версию.
  • renormalize (no-renormalize)
    Предотвращает ложные конфликты при слиянии вариантов с разными типами перевода строк.
  • diff-algorithm=[patience|minimal|histogram|myers], а так же опция patience
    Выбор алгоритма дифференциации файлов.
    Дополнительную информацию об этих опциях можно найти в документации по git-diff. Если кратко, свойства этих алгоритмов следующие:
    default, myers — стандартный, жадный алгоритм. Он используется по умолчанию.
    minimal — производится поиск минимальнейших изменений, что занимает дополнительное время.
    patience — использовать алгоритм «patience diff». О нем можно почитать у автора алгоритма, либо в сокращенном варианте на SO.
    histogram — расширяет алгоритм patience с целью, описанной как «support low-occurrence common elements». Сказать честно, я не смог найти достаточно ясного ответа на вопрос, какие конкретно случаи подразумеваются и буду очень рад, если кто-нибудь поможет найти этот ответ.
  • ignore-space-change, ignore-all-space, ignore-space-at-eol
    Корни этих опций лежат, опять же, в git-diff и относятся к дифференциации файлов при слиянии.
    ignore-space-change — игнорируются различия в количестве пробелов, идущих подряд, а так же пробелы в конце строки,
    ignore-all-space — пробелы абсолютно игнорируются при сравнении,
    ignore-space-at-eol — игнорируются различия в пробелах в конце строки.
  • rename-threshold=<n>
    Данная опция задает порог, по достижении которого файл может считаться не новым, а переименованным файлом, которого git-diff не досчитался. Например, -Xrename-threshold=90% подразумевает, что переименованным считается файл, который содержит от 90% контента некоторого удаленного файла.
  • subtree[=<path>]
    Выполнение рекурсивного слияния с этой опцией будет более продвинутым вариантом стратегии subtree, где алгоритм основывается на предположении, как деревья должны совместиться при слиянии. Вместо этого в этом случае указывается конкретный вариант.
Стратегия octopus

Эта стратегия используется для слияние более чем двух веток. Получившийся в итоге коммит будет иметь, соответственно, больше двух родителей.

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

Стратегия ours

Не следует путать стратегию ours и опцию ours стратегии recursive.

Выполняя git merge -s ours obsolete, вы как бы говорите: я хочу слить истории веток, но проигнорировать все изменения, которые произошли в ветке obsolete. Иногда рекомендуют вместо стратегии ours использовать следующий вариант:

$ git checkout obsolete
$ git merge -s recursive -Xtheirs master


Стратегия ours — более радикальное средство.

Стратегия subtree

Для иллюстрации данной стратегии возьмем пример из главы Слияние поддеревьев книги «Pro Git».

Добавим в наш проект новые удаленный репозиторий, rack:

$ git remote add rack_remote [email protected]:schacon/rack.git
$ git fetch rack_remote
warning: no common commits
remote: Counting objects: 3184, done.
remote: Compressing objects: 100% (1465/1465), done.
remote: Total 3184 (delta 1952), reused 2770 (delta 1675)
Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, done.
Resolving deltas: 100% (1952/1952), done.
From [email protected]:schacon/rack
 * [new branch]      build      -> rack_remote/build
 * [new branch]      master     -> rack_remote/master
 * [new branch]      rack-0.4   -> rack_remote/rack-0.4
 * [new branch]      rack-0.9   -> rack_remote/rack-0.9
$ git checkout -b rack_branch rack_remote/master
Branch rack_branch set up to track remote branch refs/remotes/rack_remote/master.
Switched to a new branch "rack_branch"

Ясно, что ветки master и rack_branch имеют абсолютно разные рабочие каталоги. Добавим файлы из rack_branch в master с использованием squash, чтобы избежать засорения истории ненужными нам фактами:

$ git checkout master
$ git merge --squash -s subtree --no-commit rack_branch
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested


Теперь файлы проекта rack у нас в рабочем каталоге.

Заключительное слово

Итак, я собрал вместе все знания, которые я получил за время работы с Git относительно благополучного git-merge. Я буду рад, если кому-то это поможет, но так же я буду рад, если кто-то поможет мне дополнить материал или исправить неточности и ошибки, если вдруг я допустил такие.

Обзор и примеры инструкции MERGE SQL Server

В этой статье мы рассмотрим оператор MERGE в SQL Server, альтернативы оператору MERGE, различные предложения и примеры оператора MERGE в SQL Server.

В этом посте мы рассмотрим следующие темы об операторе слияния SQL Server с некоторыми интересными примерами:

  1. Введение и синтаксис оператора слияния в SQL Server
  2. Использование оператора слияния для обновления, вставки и удаления строк в таблицах SQL Server
  3. Работа с предложением TOP в заявлении о слиянии
  4. Предложение
  5. OUTPUT в заявлении о слиянии
  6. Слияние с триггерами в SQL Server

Заявление о слиянии Введение

Оператор MERGE используется для синхронизации двух таблиц путем вставки, удаления и обновления строк целевой таблицы на основе условия соединения с исходной таблицей.Давайте обсудим несколько примеров оператора MERGE с использованием демонстрационных таблиц.

Синтаксис MERGE

Ниже приведен синтаксис оператора MERGE в SQL Server.

MERGE TOP (значение)

USING

ON

[WHEN MATCHED [AND ]

THEN ]

MATCHED [MATCHED BY NOT]

[AND ]

THEN ]

[ЕСЛИ НЕ СООТВЕТСТВУЕТ ИСТОЧНИКУ [AND ]

THEN ]

[)

]

;

Здесь я создаю образцы таблиц, чтобы показать различные примеры оператора MERGE.

Используйте нижеприведенный сценарий T-SQL для создания таблиц и вставки в них примеров данных.

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

24

25

26

27

28

29

30

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.ТАБЛИЦЫ, где name = ‘Locations_stage’)

BEGIN

DROP TABLE Locations_stage

END

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.TABLES, где name = ‘Locations’)

BEGIN

BEGIN

СОЗДАТЬ ТАБЛИЦУ [dbo]. [Locations] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

СОЗДАТЬ ТАБЛИЦУ [dbo].[Locations_stage] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

INSERT INTO Locations values ​​(1, ‘Richmond Road’) , (2, ‘Brigade Road’), (3, ‘Houston Street’)

INSERT INTO Locations_stage values ​​(1, ‘Richmond Cross’), (3, ‘Houston Street’), (4, ‘ Канал Стрит ‘)

Использование MERGE для обновления совпавших строк

Предложение WHEN MATCHED в операторе MERGE SQL Server используется для обновления, удаления строк в целевой таблице, когда строки сопоставляются с исходной таблицей на основе условия соединения.В этом случае Locations является целевой таблицей, Locations_stage — исходной таблицей, а столбец LocationID используется в условии соединения. Пожалуйста, обратитесь к приведенному ниже сценарию T-SQL для обновления совпавших строк с помощью предложения WHEN MATCHED.

MERGE Locations T

ИСПОЛЬЗОВАНИЕ Locations_stage S НА T.LocationID = S.LocationID

КОГДА СОБИРАЕТСЯ ТОГДА

НАБОР ОБНОВЛЕНИЯ LocationName = S.LocationName;

Строки с LocationID 1 и 3 сопоставляются в целевой и исходной таблице в соответствии с условием соединения, а значение LocationName в целевом объекте было обновлено значением LocationName в исходной таблице для обеих строк.

Мы также можем использовать дополнительное условие поиска вместе с предложением WHEN MATCHED в операторе MERGE SQL Server, чтобы обновлять только те строки, которые соответствуют дополнительному условию поиска.

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

24

25

26

27

28

29

30

000

000 34

35

36

37

38

39

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.ТАБЛИЦЫ, где name = ‘Locations_stage’)

BEGIN

DROP TABLE Locations_stage

END

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.TABLES, где name = ‘Locations’)

BEGIN

BEGIN

СОЗДАТЬ ТАБЛИЦУ [dbo]. [Locations] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

СОЗДАТЬ ТАБЛИЦУ [dbo].[Locations_stage] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

INSERT INTO Locations values ​​(1, ‘Richmond Road’) , (2, ‘Brigade Road’), (3, ‘Houston Street’)

INSERT INTO Locations_stage values ​​(1, ‘Richmond Cross’), (3, ‘Houston Street’), (4, ‘ Canal Street ‘)

MERGE Locations T

ИСПОЛЬЗОВАНИЕ Locations_stage S ON T.LocationID = S.LocationID

КОГДА СООТВЕТСТВУЕТ И T.LocationID = 3 ТОГДА

УСТАНОВИТЬ ОБНОВЛЕНИЕ LocationName = S.LocationName;

выберите * из местоположений

Мы видим, что оператор слияния не обновил строку с LocationID 1, поскольку он не удовлетворял дополнительному условию поиска, указанному вместе с предложением WHEN MATCHED.

В лучшем случае мы можем указать только два предложения WHEN MATCHED в операторе MERGE.Если указаны два предложения WHEN MATCHED, одно предложение должно иметь операцию обновления, а другое — операцию удаления. Пожалуйста, обратитесь к приведенному ниже сценарию T-SQL для примера оператора MERGE с двумя предложениями WHEN MATCHED.

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

24

25

26

27

28

29

30

000

000 34

35

36

37

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.ТАБЛИЦЫ, где name = ‘Locations_stage’)

BEGIN

DROP TABLE Locations_stage

END

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.TABLES, где name = ‘Locations’)

BEGIN

BEGIN

СОЗДАТЬ ТАБЛИЦУ [dbo]. [Locations] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

СОЗДАТЬ ТАБЛИЦУ [dbo].[Locations_stage] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

INSERT INTO Locations values ​​(1, ‘Richmond Road’) , (2, ‘Brigade Road’), (3, ‘Houston Street’)

INSERT INTO Locations_stage values ​​(1, ‘Richmond Cross’), (3, ‘Houston Street’), (4, ‘ Canal Street ‘)

MERGE Locations T

ИСПОЛЬЗОВАНИЕ Locations_stage S ON T.LocationID = S.LocationID

ПРИ СООТВЕТСТВИИ И T.LocationID = 3 ТОГДА

УДАЛИТЬ

ПРИ СОГЛАСОВАНИИ И T.LocationID = 1 ТОГДА

УСТАНОВИТЬ ОБНОВЛЕНИЕ LocationName = S.LocationName;

  • Примечание : мы не можем использовать одну и ту же операцию DML в обоих предложениях WHEN MATCHED.

Если в исходной таблице имеется более одной строки, которая соответствует условию соединения, обновление в инструкции MERGE SQL Server завершается ошибкой и возвращает ошибку «Оператор MERGE пытался ОБНОВИТЬ или УДАЛИТЬ одну и ту же строку более одного раза.Это происходит, когда целевая строка соответствует более чем одной исходной строке. Оператор MERGE не может ОБНОВЛЯТЬ / УДАЛИТЬ одну и ту же строку целевой таблицы несколько раз. Уточните предложение ON, чтобы целевая строка соответствовала не более одной исходной строке, или используйте предложение GROUP BY для группировки исходных строк ».

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

24

25

26

27

28

29

30

000

000 34

35

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.ТАБЛИЦЫ, где name = ‘Locations_stage’)

BEGIN

DROP TABLE Locations_stage

END

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.TABLES, где name = ‘Locations’)

BEGIN

BEGIN

СОЗДАТЬ ТАБЛИЦУ [dbo]. [Locations] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

СОЗДАТЬ ТАБЛИЦУ [dbo].[Locations_stage] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

INSERT INTO Locations values ​​(1, ‘Richmond Road’) , (2, ‘Brigade Road’), (3, ‘Houston Street’)

INSERT INTO Locations_stage values ​​(1, ‘Richmond Cross’), (3, ‘Houston Street’), (4, ‘ Canal Street ‘), (1,’ James Street ‘)

MERGE Locations T

ИСПОЛЬЗОВАНИЕ Locations_stage S ON T.LocationID = S.LocationID

КОГДА СООТВЕТСТВУЕТ ЗАТЕМ

НАБОР ОБНОВЛЕНИЯ LocationName = S.LocationName;

Использование MERGE для вставки строк в целевую таблицу

Предложение WHEN NOT MATCHED BY TARGET используется для вставки в целевую таблицу строк, которые не соответствуют условию соединения с исходной таблицей. Предложение WHEN NOT MATCHED BY TARGET можно указать только один раз в операторе MERGE SQL Server.

Например, строка с LocationID = 4 в таблице Locations_stage не соответствует условию соединения и присутствует только в исходной таблице.Теперь, когда мы используем предложение WHEN NOT MATCHED BY TARGET в операторе слияния, чтобы вставить дополнительную строку из Locations_stage в Locations.

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

24

25

26

27

28

29

30

000

34

35

36

37

38

39

40

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.ТАБЛИЦЫ, где name = ‘Locations_stage’)

BEGIN

DROP TABLE Locations_stage

END

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.TABLES, где name = ‘Locations’)

BEGIN

BEGIN

СОЗДАТЬ ТАБЛИЦУ [dbo]. [Locations] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

СОЗДАТЬ ТАБЛИЦУ [dbo].[Locations_stage] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

INSERT INTO Locations values ​​(1, ‘Richmond Road’) , (2, ‘Brigade Road’), (3, ‘Houston Street’)

INSERT INTO Locations_stage values ​​(1, ‘Richmond Cross’), (3, ‘Houston Street’), (4, ‘ Canal Street ‘)

MERGE Locations T

ИСПОЛЬЗОВАНИЕ Locations_stage S ON T.LocationID = S.LocationID

КОГДА НЕ СООТВЕТСТВУЕТ ЦЕЛИ

ТОГДА

INSERT (LocationID, LocationName)

ЗНАЧЕНИЯ (S.LocationID, S.LocationName);

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

Использование MERGE для удаления строк в целевой таблице.

Мы можем использовать предложение WHEN NOT MATCHED BY SOURCE в операторе MERGE SQL Server, чтобы удалить строки в целевой таблице, которые не соответствуют условию соединения с исходной таблицей.

Например, строка с locationID = 2 в целевой таблице не соответствует условию соединения, и строка присутствует только в целевой таблице. Итак, когда мы используем WHEN NOT MATCHED BY SOURCE и можем либо удалить строку, либо обновить ее. Пожалуйста, обратитесь к приведенному ниже сценарию T-SQL, чтобы удалить строку в целевой таблице с помощью предложения WHEN NOT MATCHED BY SOURCE.

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

24

25

26

27

28

29

30

000

000 34

35

36

37

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.ТАБЛИЦЫ, где name = ‘Locations_stage’)

BEGIN

DROP TABLE Locations_stage

END

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.TABLES, где name = ‘Locations’)

BEGIN

BEGIN

СОЗДАТЬ ТАБЛИЦУ [dbo]. [Locations] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

СОЗДАТЬ ТАБЛИЦУ [dbo].[Locations_stage] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

INSERT INTO Locations values ​​(1, ‘Richmond Road’) , (2, ‘Brigade Road’), (3, ‘Houston Street’)

INSERT INTO Locations_stage values ​​(1, ‘Richmond Cross’), (3, ‘Houston Street’), (4, ‘ Canal Street ‘)

MERGE Locations T

ИСПОЛЬЗОВАНИЕ Locations_stage S ON T.LocationID = S.LocationID

ПРИ НЕ СООТВЕТСТВУЕТ ИСТОЧНИКУ

ТО

УДАЛИТЬ;

Предложение WHEN NOT MATCHED BY SOURCE нельзя использовать более двух раз. Если предложение WHEN NOT MATCHED BY SOURCE в инструкции SQL Server MERGE было указано два раза, одна должна использовать операцию обновления, а другая должна использовать операцию удаления. Пожалуйста, обратитесь к сценарию T-SQL ниже, чтобы дважды использовать предложение WHEN NOT MATCHED BY SOURCE.

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

24

25

26

27

28

29

30

000

000 34

35

36

37

38

39

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.ТАБЛИЦЫ, где name = ‘Locations_stage’)

BEGIN

DROP TABLE Locations_stage

END

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.TABLES, где name = ‘Locations’)

BEGIN

BEGIN

СОЗДАТЬ ТАБЛИЦУ [dbo]. [Locations] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

СОЗДАТЬ ТАБЛИЦУ [dbo].[Locations_stage] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

INSERT INTO Locations values ​​(1, ‘Richmond Road’) , (2, ‘Brigade Road’), (3, ‘Houston Street’), (6, ‘James Street’)

INSERT INTO Locations_stage values ​​(1, ‘Richmond Cross’), (3, ‘ Houston Street ‘), (4,’ Canal Street ‘)

MERGE Locations T

ИСПОЛЬЗОВАНИЕ Locations_stage S НА T.LocationID = S.LocationID

КОГДА НЕ СООТВЕТСТВУЕТ ИСТОЧНИКУ И LocationID = 2

ТОГДА

УДАЛИТЬ

ЕСЛИ НЕ СООТВЕТСТВУЕТ ИСТОЧНИКУ И LocationID = 6

ТОГДА ОБНОВИТЬ НАБОР LocationName = ‘Test’;

Мы можем использовать все три предложения в одном операторе слияния для синхронизации целевой таблицы с исходной таблицей. Обратитесь к образцу сценария T-SQL, чтобы синхронизировать целевую таблицу с исходной таблицей с помощью оператора MERGE и всех трех предложений.

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

24

25

26

27

28

29

30

000

34

35

36

37

38

39

40

41

42

43

44

45

46

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.ТАБЛИЦЫ, где name = ‘Locations_stage’)

BEGIN

DROP TABLE Locations_stage

END

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.TABLES, где name = ‘Locations’)

BEGIN

BEGIN

СОЗДАТЬ ТАБЛИЦУ [dbo]. [Locations] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

СОЗДАТЬ ТАБЛИЦУ [dbo].[Locations_stage] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

INSERT INTO Locations values ​​(1, ‘Richmond Road’) , (2, ‘Brigade Road’), (3, ‘Houston Street’)

INSERT INTO Locations_stage values ​​(1, ‘Richmond Cross’), (3, ‘Houston Street’), (4, ‘ Canal Street ‘)

MERGE Locations T

ИСПОЛЬЗОВАНИЕ Locations_stage S ON T.LocationID = S.LocationID

КОГДА СООТВЕТСТВУЕТ ТОГДА

НАБОР ОБНОВЛЕНИЯ LocationName = S.LocationName

КОГДА НЕ СООТВЕТСТВУЕТ ЦЕЛИ

ТОГДА

INSERT (Location

) INSERT (Location

) , S.LocationName)

ЕСЛИ ИСТОЧНИК НЕ СООТВЕТСТВУЕТ

THEN

DELETE;

Предложение TOP в MERGE

Предложение TOP в операторе MERGE используется для ограничения количества затронутых строк.Предложение TOP применяется после удаления всех строк, которые не подходят для операций вставки, обновления и удаления. Пожалуйста, обратитесь к приведенному ниже сценарию T-SQL для инструкции SQL Server MERGE с предложением TOP.

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

24

25

26

27

28

29

30

000

34

35

36

37

38

39

40

41

42

43

44

45

46

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.ТАБЛИЦЫ, где name = ‘Locations_stage’)

BEGIN

DROP TABLE Locations_stage

END

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.TABLES, где name = ‘Locations’)

BEGIN

BEGIN

СОЗДАТЬ ТАБЛИЦУ [dbo]. [Locations] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

СОЗДАТЬ ТАБЛИЦУ [dbo].[Locations_stage] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

INSERT INTO Locations values ​​(1, ‘Richmond Road’) , (2, ‘Brigade Road’), (3, ‘Houston Street’)

INSERT INTO Locations_stage values ​​(1, ‘Richmond Cross’), (3, ‘Houston Street’), (4, ‘ Canal Street ‘), ()

MERGE top (1) Locations T

ИСПОЛЬЗОВАНИЕ Locations_stage S ON T.LocationID = S.LocationID

КОГДА СООТВЕТСТВУЕТ ТОГДА

НАБОР ОБНОВЛЕНИЯ LocationName = S.LocationName

КОГДА НЕ СООТВЕТСТВУЕТ ЦЕЛИ

ТОГДА

INSERT (Location

) INSERT (Location

) , S.LocationName)

ЕСЛИ ИСТОЧНИК НЕ СООТВЕТСТВУЕТ

THEN

DELETE;

Мы можем видеть, что обновляется только строка с LocationID = 1, а строки, которые не были сопоставлены источником, не удаляются, а строки, которые не были сопоставлены целевым объектом, не вставляются.

Предложение

OUTPUT в MERGE

Предложение OUTPUT в операторе слияния вернет по одной строке для каждой строки, измененной в целевой таблице. $ action используется, чтобы узнать, была ли строка в целевой таблице удалена, вставлена ​​или обновлена. Следующий сценарий T-SQL является примером предложения OUTPUT в операторе MERGE.

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

24

25

26

27

28

29

30

000

34

35

36

37

38

39

40

41

42

43

44

45

46

47

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.ТАБЛИЦЫ, где name = ‘Locations_stage’)

BEGIN

DROP TABLE Locations_stage

END

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.TABLES, где name = ‘Locations’)

BEGIN

BEGIN

СОЗДАТЬ ТАБЛИЦУ [dbo]. [Locations] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

СОЗДАТЬ ТАБЛИЦУ [dbo].[Locations_stage] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

INSERT INTO Locations values ​​(1, ‘Richmond Road’) , (2, ‘Brigade Road’), (3, ‘Houston Street’)

INSERT INTO Locations_stage values ​​(1, ‘Richmond Cross’), (3, ‘Houston Street’), (4, ‘ Canal Street ‘)

MERGE Locations T

ИСПОЛЬЗОВАНИЕ Locations_stage S ON T.LocationID = S.LocationID

КОГДА СООТВЕТСТВУЕТ ТОГДА

НАБОР ОБНОВЛЕНИЯ LocationName = S.LocationName

КОГДА НЕ СООТВЕТСТВУЕТ ЦЕЛИ

ТОГДА

INSERT (Location

) INSERT (Location

) , S.LocationName)

КОГДА НЕ СООТВЕТСТВУЕТ ИСТОЧНИКУ

ТОГДА

УДАЛИТЬ

ВЫХОД УДАЛЕН. *, $ Action AS [Действие], ВСТАВЛЕНО. *;

Пожалуйста, обратитесь к изображению ниже для вывода вышеуказанного сценария, который показывает действие, а также вставленные и удаленные данные в операторе MERGE SQL Server.вы также можете вставить выходные данные в другую таблицу, если вы хотите отслеживать или проверять изменения позже.

Использование MERGE для таблицы с триггерами

Если мы создаем вместо триггеров в целевой таблице, мы должны создавать вместо триггеров для всех действий DML, указанных в операторе MERGE. Если мы создадим только триггер INSTEAD OF INSERT для целевой таблицы и укажем операцию INSERT, DELETE И UPDATE в операторе MERGE, это вызовет ошибку.

Ниже приведен пример сценария T-SQL с триггером INSTEAD OF INSERT для целевой таблицы и всеми тремя операциями DML в операторе MERGE.

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

24

25

26

27

28

29

30

000

34

35

36

37

38

39

40

41

42

43

44

45

46

49

0002 47

00030002 47

0003

51

52

53

54

55

56

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.ТАБЛИЦЫ, где name = ‘Locations_stage’)

BEGIN

DROP TABLE Locations_stage

END

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.TABLES, где name = ‘Locations’)

BEGIN

BEGIN

СОЗДАТЬ ТАБЛИЦУ [dbo]. [Locations] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

СОЗДАТЬ ТАБЛИЦУ [dbo].[Locations_stage] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

INSERT INTO Locations values ​​(1, ‘Richmond Road’) , (2, ‘Brigade Road’), (3, ‘Houston Street’)

INSERT INTO Locations_stage values ​​(1, ‘Richmond Cross’), (3, ‘Houston Street’), (4, ‘ Canal Street ‘)

GO

CREATE TRIGGER TEMP ON Locations

INSTEAD OF INSERT

AS

BEGIN

PRINT’ Hello ‘

END

GE

GE

GE

ИСПОЛЬЗОВАНИЕ Locations_stage S НА T.LocationID = S.LocationID

КОГДА СООТВЕТСТВУЕТ ТОГДА

НАБОР ОБНОВЛЕНИЯ LocationName = S.LocationName

КОГДА НЕ СООТВЕТСТВУЕТ ЦЕЛИ

ТОГДА

INSERT (Location

) INSERT (Location

) , S.LocationName)

ЕСЛИ ИСТОЧНИК НЕ СООТВЕТСТВУЕТ

THEN

DELETE;

Пожалуйста, обратитесь к примеру ниже вместо триггера для всех действий, указанных в операторе слияния.

1

2

3

4

5

6

7

8

9

10

11

12

13

140002

14

18

19

20

21

22

23

24

25

26

27

28

29

30

000

34

35

36

37

38

39

40

41

42

43

44

45

46

49

00030002 47

00030002 47

0003

51

52

53

54

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.ТАБЛИЦЫ, где name = ‘Locations_stage’)

BEGIN

DROP TABLE Locations_stage

END

ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ИЗ SYS.TABLES, где name = ‘Locations’)

BEGIN

BEGIN

СОЗДАТЬ ТАБЛИЦУ [dbo]. [Locations] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

СОЗДАТЬ ТАБЛИЦУ [dbo].[Locations_stage] (

[LocationID] [int] NULL,

[LocationName] [varchar] (100) NULL

)

GO

INSERT INTO Locations values ​​(1, ‘Richmond Road’) , (2

.

SQL Server 2008 Пример инструкции T-SQL MERGE

Microsoft SQL Server 2008 имеет усовершенствования T-SQL, такие как SQL MERGE statement , для разработчиков sql и администраторов баз данных SQL Server (DBA).

SQL Server 2008 MERGE T-SQL команду можно использовать для вставки, обновления и / или удаления в одном операторе sql.
Команда T-SQL Merge сравнит два набора данных или две таблицы.
Если есть совпадающие, то команда Merge обновит совпадающие.
Если есть несогласованные строки из одного набора данных в другой, тогда Merge вставит недостающие строки.
Команду слияния также можно использовать для удаления несовпадающих из основной таблицы.

Вот пример слияния, который следует запустить в базах данных MS SQL Server 2008, чтобы просмотреть результаты команды T-SQL MERGE.

СОЗДАТЬ ТАБЛИЦЫ Книги (
BookId smallint,
Заголовок varchar (100),
Автор varchar (25),
ISBN varchar (50),
Страницы int
)
GO
ВСТАВИТЬ В КНИГИ ЗНАЧЕНИЕ
(1, «Microsoft SQL Server 2005 для чайников», «Эндрю Ватт», NULL, NULL),
(2, 'Microsoft SQL Server 2005 для чайников', NULL, NULL, 432),
(3, «Microsoft SQL Server 2005 для чайников», NULL, «978-0-7645-7755-0», NULL)
GO
ВЫБРАТЬ * ИЗ Книг

Вот как данные в таблице sql Books отображаются после выполнения оператора SELECT.

Как разработчик T-SQL я хочу преобразовать указанные выше 3 строки данных в одну строку.
В некотором смысле я хочу сгруппировать эти столбцы, взяв за основу название книги.
Также я хочу объединить эти три строки в одну. Это означает, что при обновлении значений столбцов одной строки я должен избавиться от других строк таблицы. Это означает, что я удалю повторяющиеся строки, взяв за основу название книги для сравнения всех строк таблицы sql.

Приведенный ниже оператор t-sql GROUP BY выбирает нужные мне данные, но не обновляет строку и не удаляет повторяющиеся строки в таблице sql.

ВЫБРАТЬ
МАКС (BookId) BookId,
Титул,
MAX (Автор) Автор,
МАКС. (ISBN) ISBN,
МАКС (страниц) Страниц
ИЗ Книги
ГРУППА ПО Титулу

Используя команду MS SQL Server 2008 T-SQL Merge, мы теперь создадим один единственный оператор, который обновит одну строку и удалит остальные из таблицы sql.
Вот код для примера слияния t-sql

MERGE Книги
ИСПОЛЬЗОВАНИЕ
(
ВЫБРАТЬ
МАКС (BookId) BookId,
Титул,
MAX (Автор) Автор,
МАКС. (ISBN) ISBN,
МАКС (страниц) Страниц
ИЗ Книги
ГРУППА ПО Титулу
) MergeData ON Books.BookId = MergeData.BookId
КОГДА СООТВЕТСТВОВАЛИ
НАБОР ОБНОВЛЕНИЙ
Книги.Title = MergeData.Title,
Books.Author = MergeData.Author,
Books.ISBN = MergeData.ISBN,
Books.Pages = MergeData.Pages
ЕСЛИ НЕ ПОДХОДИТ ПО ИСТОЧНИКУ, ТО УДАЛИТЬ;
GO
ВЫБРАТЬ * ИЗ Книг

И набор результатов вышеупомянутого оператора select после выполнения команды Merge такой же, как мы и планировали.
Надеюсь, вам понравился этот пример слияния T-SQL SQL Server 2008 T-SQL.
Вы можете найти аналогичный учебник по команде слияния в статье «Улучшение команды слияния T-SQL» и «Пример» в SQL Server 2008.
Также обратитесь к разделу «Слияние SQL в триггере» для получения дополнительных примеров команд слияния SQL Server. Здесь утилита SQLCMD и команда SQL Merge используются вместе для создания удобного инструмента для администраторов баз данных.

.

Microsoft SQL Server — MERGE

Введение

Начиная с SQL Server 2008, можно выполнять операции вставки, обновления или удаления в одном операторе с помощью оператора MERGE.

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

Синтаксис

  • Согласно MSDN — https: // msdn.microsoft.com/en-us/library/bb510625.aspx [WITH [, … n]] MERGE [TOP (выражение) [PERCENT]] [INTO] [WITH ()] [[ AS] псевдоним_таблицы] USING ON [ КОГДА ИМЕЕТСЯ [И <условие_поиска>] ТОГДА <совпадение_состава>] [… n] [ЕСЛИ НЕ СОГЛАСОВАНО [ПО ЦЕЛИ] [И ] THEN ] [КОГДА НЕ СООТВЕТСТВУЕТ ИСТОЧНИКУ [И ] THEN ] […n] [] [OPTION ( [, … n])]; :: = {[имя_базы_данных. schema_name. | schema_name. ] target_table} :: = {{[ [, … n]] [[,] ИНДЕКС (index_val [, … n] )]}} :: = {table_or_view_name [[AS] псевдоним_таблицы ] [] [WITH (table_hint [[,] … n])] | rowset_function [[AS] псевдоним_таблицы] [(псевдоним_колонки [,…n ])] | user_defined_function [[AS] псевдоним_таблицы] | OPENXML | производная_таблица [AS] псевдоним_таблицы [(псевдоним_столбца [, … n])] | | | } :: = :: = {UPDATE SET | УДАЛИТЬ} :: = SET { column_name = {выражение | ПО УМОЛЧАНИЮ | NULL} | {udt_column_name. {{ имя_свойства = выражение | field_name = выражение} | имя_метода (аргумент [,.= | | =} выражение} [, … n] <слияние_не совпадений> :: = {INSERT [( список_столбцов)] {ЗНАЧЕНИЯ (список_значений) | ЗНАЧЕНИЯ ПО УМОЛЧАНИЮ } } <условие_поиска> :: = <условие_поиска> :: = {[НЕ] | ( <условие_поиска>)} [{И | ИЛИ} [НЕ] {| ( )}] [, … n] :: = {выражение {= | <> | ! = |

    | > = | ! > | <| <= | ! <} выражение | строковое_выражение [НЕ] КАК строковое_выражение [ESCAPE 'escape_character'] | выражение [ НЕ] МЕЖДУ выражением И выражением | выражение IS [NOT] NULL | СОДЕРЖИТ ({столбец | *}, '‘) | FREETEXT ({столбец | *}, ‘freetext_string’) | выражение [НЕ] IN (подзапрос | выражение [,…n]) | выражение {= | <> | ! = | | > = | ! > | <| <= | ! <} {ВСЕ | НЕКОТОРЫЕ | ЛЮБОЙ} (подзапрос) | EXISTS (подзапрос)} :: = {[OUTPUT INTO {@table_variable | output_table} [(column_list)]] [ВЫВОД ]} :: = { | скалярное_выражение} [[AS] идентификатор_алиас_столбца] [, … n] <имя_столбца> :: = {УДАЛЕНО | ВСТАВЛЕННЫЙ | from_table_name}.{* | column_name} | $ действие

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




.

SELECT, INSERT, UPDATE с оператором SQL MERGE

Введение

Разработчики Business Intelligence называют это медленно изменение размера. Разработчики баз данных называют это UPSERT . Будь то медленно меняющийся размер или UPSERT , базовый образец остается прежним: ОБНОВЛЕНИЕ данных, если ключ существует и если ключ не существует ВСТАВЬТЕ данные. Это утомительный код для написания, сложный код для поддержки и медленно выполнять.Однако, начиная с SQL Server 2008, шаблон был заключен в новый MERGE Утверждение. Я собираюсь продемонстрировать, как и когда использовать новый отчет TSQL MERGE . Я собираюсь начать с некоторой предысторией на UPSERTs и замедлении изменение размеров.

UPSERTS и медленно меняющиеся размеры

Как я упоминал ранее, UPSERTS и медленно Изменение размеров — это термины для добавления или альтернативы обновление записи в базе данных в зависимости от того, запись существует или не существует.Обычно решение алгоритм работает примерно так:

  1. Поиск записи с помощью ключа таблицы
  2. Если значение ключа отсутствует, вставить новую запись
  3. Если значение ключа существует, обновить запись

Для таблицы, подобной приведенной ниже:

 СОЗДАТЬ ТАБЛИЦУ [dbo]. [ToMergeTable] (
 [KeyField] [int] НЕ NULL,
 [Поле1] [nvarchar] (50) НЕ ПУСТО,
 [Поле2] [nvarchar] (50) НЕ NULL,
 [UpdateDateField] [datetime] НЕ ПУСТО,
  ОГРАНИЧЕНИЕ [PK_ToMergeTable] ПЕРВИЧНЫЙ КЛЮЧ КЛАСТЕРИРОВАН
 (
 [KeyField] ASC
 ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
 ) НА [ПЕРВИЧНОМ]
 
 Код TSQL может выглядеть так, как показано ниже.ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ * ИЗ ToMergeTable, ГДЕ KeyField = @KeyField)
 НАЧАТЬ
 ОБНОВЛЕНИЕ ToMergeTable SET UpdateDateField = GETDATE () WHERE KeyField = @KeyField
 ВЫБЕРИТЕ "ОБНОВЛЕНИЕ"
 КОНЕЦ
 ELSE
 НАЧАТЬ
 ВСТАВИТЬ В ToMergeTable (KeyField, Field1, Field2, UpdateDateField) VALUES (@ KeyField, @ Field1 + '- 1', @ Field2 + '- 1', GETDATE ())
 ВЫБЕРИТЕ 'Сделано INSERT'
 КОНЕЦ
 

Нет ничего технически неправильного в заявлении выше, но есть ряд недостатков в решение.

Сначала оператор SELECT отделяется из INSERT и UPDATE заявление.Базы данных обычно имеют одновременных пользователей. в время между выполнением SELECT и, для Например, оператор INSERT , другой пользователь может добавили новую запись через долю секунды после SELECT инструкция выполняет одну из ВСТАВКИ не работают.

Кроме того, приведенный выше код требует двух циклических обращений к база данных; одна поездка, чтобы найти запись, SELECT инструкция и вторая поездка для выполнения соответствующий DML ( ОБНОВЛЕНИЕ или ВСТАВИТЬ ).Кроме того, код работает только на одном запись за раз.

Я мог бы внести некоторые улучшения в код, но несмотря ни на что улучшения, которые я делаю, должны выполняться два утверждения. За Например, код можно изменить для использования временной таблицы и коррелированный подзапрос к INSERT , если данные временной таблицы отсутствуют и ОБНОВЛЕНИЕ WHERE данные временной таблицы совпадают с чем-то в существующая таблица.

Опять же, улучшения кодирования технически верны и более гибкий.Однако часто кодирование подзапроса жертвует удобочитаемостью, плюс, как я упоминал ранее, не избежать выполнения как минимум двух операторов и кодирования более одного утверждения означает два предложения WHERE сохранить, если ключ изменится.

С примером без MERGE и со сценарием MERGE я собираюсь чтобы объяснить, как решение улучшается с MERGE заявление.

Обзор MERGE

Ниже приведен алгоритм решения выше, реализованный с использованием заявление MERGE .

  ОБЪЕДИНИТЬ В ToMergeTable как T
  ИСПОЛЬЗОВАНИЕ (ЗНАЧЕНИЯ
 (@ KeyField, @ Field1 + '- 1', @ Field2 + '- 1', GETDATE ())
 , (@ KeyField + 1, @ Field1 + '- 2', @ Field2 + '- 2', GETDATE ())
 , (@ KeyField + 2, @ Field1 + '- 3', @ Field2 + '- 3', GETDATE ())
  ) AS S (KeyField, Поле1, Поле2, UpdateDate)
  ВКЛ T.KeyField = S.KeyField
  КОГДА ИМЕЕТСЯ ТО - ОБНОВЛЕНИЕ
 ОБНОВЛЕНИЕ НАБОР UpdateDateField = UpdateDate
  КОГДА НЕ СООТВЕТСТВУЕТ - ВСТАВЬТЕ
 INSERT (KeyField, Field1, Field2, UpdateDateField) VALUES (S.KeyField, S.Field1, S.Field2, UpdateDate)
  OUTPUT $ action КАК ChangesMade;
 

Позже в этой статье я объясню, что каждая часть заявление делает, сначала некоторые общие мысли.Целиком решение заключено в один оператор. Итак, нет разделение операторов и отсутствие необходимости запускать более одно заявление. Улучшается читаемость и ремонтопригодность. Более того, MERGE существует по несколько более высокой цене. уровень абстракции, чем SELECT , ВСТАВИТЬ , ОБНОВЛЕНИЕ . Это не загадка что более высокие уровни абстракции часто приводят к более быстрому разработка и лучшее сопровождение кода. Одно заявление означает, что код выполняется в неявной транзакции.Два отдельные заявления могли потребовать BEGIN / COMMIT / ROLLBACK транзакция.

Теперь я собираюсь показать, как составить утверждение выше. и объясните варианты каждого раздела утверждения.

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Theme: Overlay by Kaira Extra Text
Cape Town, South Africa