Многострочный UPSERT (INSERT или UPDATE) от Python - PullRequest
0 голосов
/ 02 мая 2018

В настоящее время я выполняю простой запрос ниже с помощью python, используя pyodbc для вставки данных в таблицу сервера SQL:

import pyodbc

table_name = 'my_table'
insert_values = [(1,2,3),(2,2,4),(3,4,5)]

cnxn = pyodbc.connect(...)
cursor = cnxn.cursor()
cursor.execute(
    ' '.join([
        'insert into',
        table_name,
        'values',
        ','.join(
            [str(i) for i in insert_values]
        )
    ])
)
cursor.commit()

Это должно работать, пока нет повторяющихся ключей (предположим, что первый столбец содержит ключ). Однако для данных с дублирующимися ключами (данные уже существуют в таблице) это вызовет ошибку. Как можно за один раз вставить несколько строк в таблицу сервера SQL с помощью pyodbc, чтобы данные с дублирующимися ключами просто обновлялись.

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

1 Ответ

0 голосов
/ 02 мая 2018

Это можно сделать с помощью MERGE. Допустим, у вас есть ключевой столбец ID и два столбца col_a и col_b (необходимо указать имена столбцов в операторах обновления), тогда оператор будет выглядеть следующим образом:

MERGE INTO MyTable as Target
USING (SELECT * FROM 
       (VALUES (1, 2, 3), (2, 2, 4), (3, 4, 5)) 
       AS s (ID, col_a, col_b)
      ) AS Source
ON Target.ID=Source.ID
WHEN NOT MATCHED THEN
INSERT (ID, col_a, col_b) VALUES (Source.ID, Source.col_a, Source.col_b)
WHEN MATCHED THEN
UPDATE SET col_a=Source.col_a, col_b=Source.col_b;

Вы можете попробовать его на rextester.com / IONFW62765 .

По сути, я создаю Source таблицу «на лету», используя список значений, который вы хотите upsert . Затем, когда вы объединяете таблицу Source с Target, вы можете проверить условие MATCHED (Target.ID=Source.ID) в каждой строке (тогда как при использовании простого условия IF <exists> INSERT (...) ELSE UPDATE (...) вы будете ограничены одной строкой). ).

В python с pyodbc это должно выглядеть примерно так:

import pyodbc

insert_values = [(1, 2, 3), (2, 2, 4), (3, 4, 5)]
table_name = 'my_table'
key_col = 'ID'
col_a = 'col_a'
col_b = 'col_b'

cnxn = pyodbc.connect(...)
cursor = cnxn.cursor()
cursor.execute(('MERGE INTO {table_name} as Target '
                'USING (SELECT * FROM '
                '(VALUES {vals}) '
                'AS s ({k}, {a}, {b}) '
                ') AS Source '
                'ON Target.ID=Source.ID '
                'WHEN NOT MATCHED THEN '
                'INSERT ({k}, {a}, {b}) VALUES (Source.{k}, Source.{a}, Source.{b}) '
                'WHEN MATCHED THEN '
                'UPDATE SET {k}=Source.{a}, col_b=Source.{b};'
                .format(table_name=table_name,
                        vals=','.join([str(i) for i in insert_values]),
                        k=key_col,
                        a=col_a,
                        b=col_b)))
cursor.commit()

Подробнее о MERGE можно прочитать в документах по SQL Server .

...