Multi-row UPSERT (INSERT or UPDATE) from Python

前端 未结 3 930
我寻月下人不归
我寻月下人不归 2021-01-12 19:12

I am currently executing the simply query below with python using pyodbc to insert data in SQL server table:

import pyodbc

table_name = \'my_table\'
insert_         


        
3条回答
  •  无人共我
    2021-01-12 19:34

    This can be done using MERGE. Let's say you have a key column ID, and two columns col_a and col_b (you need to specify column names in update statements), then the statement would look like this:

    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;
    

    You can give it a try on rextester.com/IONFW62765.

    Basically, I'm creating a Source table "on-the-fly" using the list of values, which you want to upsert. When you then merge the Source table with the Target, you can test the MATCHED condition (Target.ID=Source.ID) on each row (whereas you would be limited to a single row when just using a simple IF INSERT (...) ELSE UPDATE (...) condition).

    In python with pyodbc, it should probably look like this:

    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()
    

    You can read up more on MERGE in the SQL Server docs.

提交回复
热议问题