Хранимая процедура, которая сравнивает Table_1 и Table_2 и обновляет Table_2 в соответствии с данными, измененными в Table_1.

Предположим, у меня есть две таблицы Table_1 и Table_2.

Оба имеют одинаковые столбцы.

@Table_1

| Id | Col1 | Col2 | Col3 |
| 1  |   a  |   b  |  c   |
| 2  |   d  |   e  |  f   |

а также

@Table_2

| Id | Col1 | Col2 | Col3 |
| 1  |   a  |   0  |  0   |
| 3  |   z  |   z  |  y   |

Как я могу написать хранимую процедуру, которая будет принимать строки из Table_1, сравнивать каждый столбец этой строки со строкой в ​​Table_2 и соответственно обновлять столбцы Table_2. И если строка в Table_1 не найдена в Table_2, просто вставьте ее.

В настоящее время. Я понимаю, что INSERT написать легко, что, вероятно, будет выглядеть так:

insert into @Table_2(col1, col2, col3)
select col1, col2, col3 from @Table_1 where id = @id

Конечный результат для Table_2 после выполнения хранимой процедуры должен выглядеть так

@Table_2

| Id | Col1 | Col2 | Col3 |
| 1  |   a  |   b  |  c   |
| 2  |   d  |   e  |  f   |
| 3  |   z  |   z  |  y   |

Как насчет сравнения каждой строки и столбца Table_1 с данными в Table_2?

Ответ @Martyn Meeks работает как два отдельных утверждения!

Согласно https://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/, предоставленный пользователем @SQL_M с использованием операторов MERGE, не идеален, но работает

Скрипт @Jayasurya Satheesh тоже работает, но использует оператор MERGE


person TheOneAndOnlyNoobofCSharp    schedule 29.08.2018    source источник


Ответы (3)


Если вас беспокоят потенциальные проблемы с оператором MERGE, как уже упоминалось, вы можете сделать это в двух отдельных операторах.

    UPDATE T2
    SET T2.Col1 = T1.Col1,
        T2.Col2 = T1.Col2,
        T2.Col3 = T1.Col3
    FROM @Table_2 T2
    INNER JOIN @Table_1 T1
    ON T2.Id = T1.Id

    INSERT INTO @Table_2 (Id,Col1,Col2,Col3)
    SELECT T1.Id,T1.Col1,T1.Col2,T1.Col3
    FROM @Table_1 T1
    WHERE NOT EXISTS (SELECT 1 FROM @Table_2 T2 WHERE T2.Id = T1.Id)

РЕДАКТИРОВАТЬ: переключил операторы обновления и вставки, как предложил Джаясурья. В противном случае вновь вставленные строки обновляются, а также вставляются, что не нужно.

person Martyn Meeks    schedule 29.08.2018
comment
Спасибо! Будет избегать операторов MERGE - person TheOneAndOnlyNoobofCSharp; 29.08.2018
comment
Я бы предпочел сначала выполнить обновление, а затем выполнить вставку, потому что в противном случае вы также будете обновлять недавно вставленные записи, что является пустой тратой времени. - person Jayasurya Satheesh; 29.08.2018
comment
Да, очень хороший момент. Их обязательно нужно поменять местами - person Martyn Meeks; 29.08.2018
comment
@MartynMeeks Как мне их переключить? - person TheOneAndOnlyNoobofCSharp; 29.08.2018
comment
поместите оператор обновления перед оператором вставки. Таким образом, как говорит Джаясурья, обновление не будет работать с существующими строками. Я изменил ответ, чтобы показать, что это значит - person Martyn Meeks; 29.08.2018

Вставка и обновление с помощью одного оператора Может быть достигнуто с помощью SQL Merge Join

Как этот пример ниже:

MERGE Table1 T1
    USING Table2 T2
        ON T1.Id = T2.Id
    WHEN MATCHED
        UPDATE SET 
            T1.Col1 = T2.Col1,
            T1.Col2 = T2.Col2,
            T1.Col3 = T2.Col3
    WHEN NOT MATCHED BY TARGET
        INSERT(COL1,COL2,COL3)
        VALUES(T2.COL1,T2.COL2,T2.COL3)

Здесь я обновляю записи в таблице 1, если есть совпадения, найденные на основе идентификатора, или иным образом вставляю записи, если совпадения нет.

person Jayasurya Satheesh    schedule 29.08.2018
comment
Хотя это правда, я бы не советовал использовать слияние, так как есть некоторые потенциальные недостатки: mssqltips.com/sqlservertip/3074/ - person SQL_M; 29.08.2018
comment
Это работает. Но нужно поменять местами Table_1 и Table_2 в скрипте. Благодарю вас! - person TheOneAndOnlyNoobofCSharp; 29.08.2018
comment
@TheOneAndOnlyNoobofCSharp Всего два отдельных оператора: один для вставки, а другой для обновлений. - person SQL_M; 29.08.2018
comment
@SQL_M спасибо. В статье упоминается только Sql Server 2008. Применяются ли эти ошибки и функции для более новых серверов Sql, таких как SQL 2016? - person TheOneAndOnlyNoobofCSharp; 29.08.2018

Создайте заявление MERGE.

CREATE PROCEDURE [dbo].[IMPORT_Data]

AS

SET NOCOUNT ON;

MERGE Table1 AS TRGT
USING Table2 AS SRCE
   ON SRCE.Id = TRGT.Id
WHEN MATCHED THEN UPDATE 
        SET TRGT.Col1 = SRCE.Col1,
            TRGT.Col2 = SRCE.Col2,
            TRGT.Col3 = SRCE.Col3,
            TRGT.Col4 = SRCE.Col4
WHEN NOT MATCHED BY TARGET THEN 
            INSERT
            (
                Col1,
                Col2,
                Col3,
                Col4
            )
            VALUES
            (
                SRCE.Col1,
                SRCE.Col2,
                SRCE.Col3,
                SRCE.Col4
            )
WHEN NOT MATCHED BY SOURCE THEN 
          DELETE;
person mvisser    schedule 29.08.2018