2016-05-03 14 views
5

In uno script python, ho bisogno di eseguire una query su un'origine dati e inserire ogni riga da quella query in una tabella su un'origine dati diversa. Lo farei normalmente con una singola istruzione insert/select con un join server collegato a tsql ma non ho una connessione server collegata a questa particolare origine dati.basic bulk pyodbc insert

Non riesco a trovare un semplice esempio di pyodbc. Ecco come lo farei, ma suppongo che l'esecuzione di un'istruzione di inserimento all'interno di un ciclo sia piuttosto lenta.

result = ds1Cursor.execute(selectSql) 

for row in result: 
    insertSql = "insert into TableName (Col1, Col2, Col3) values (?, ?, ?)" 
    ds2Cursor.execute(insertSql, row[0], row[1], row[2]) 
    ds2Cursor.commit() 

Esiste un modo migliore per inserire record con pyodbc? O è questo un modo relativamente efficiente per farlo comunque. Sto usando SqlServer 2012 e le ultime versioni di pyodbc e python.

risposta

7

Il modo migliore per gestire questo è utilizzare la funzione pyodbc executemany.

ds1Cursor.execute(selectSql) 
result = ds1Cursor.fetchall() 


ds2Cursor.executemany('INSERT INTO [TableName] (Col1, Col2, Col3) VALUES (?, ?, ?)', result) 
ds2Cursor.commit() 
+8

Solo una nota, executemany in realtà non fa vero bulkinsert. Dietro la scena fa ancora l'inserto 1 per 1. È davvero un wrapper che consente ai dati di essere acquisiti in modo più pitone. Questo post SO presenta un bulkinsert adeguato. http://stackoverflow.com/questions/29638136/how-to-speed-up-with-bulk-insert-to-ms-server-from-python-with-pyodbc-from-csv – casbby

4

Ecco una funzione che può eseguire l'inserimento di massa nel database di SQL Server.

import pypyodbc 
import contextlib 

def bulk_insert(table_name, file_path): 
    string = "BULK INSERT {} FROM '{}' (WITH FORMAT = 'CSV');" 
    with contextlib.closing(pypyodbc.connect("MYCONN")) as conn: 
     with contextlib.closing(conn.cursor()) as cursor: 
      cursor.execute(string.format(table_name, file_path)) 
     conn.commit() 
     conn.close() 

Questo funziona sicuramente. A causa di aggiornamenti, è meglio usare pypyodbc invece di pyodbc.

+1

Questa è la risposta corretta, e dovrebbe essere accettato come tale. Il metodo executemany non sostituisce la velocità dell'inserto di massa. Di nota, se si desidera eseguire un inserimento di massa da un iteratore anziché da un file sullo stesso SQL Server, il driver ctds è un'opzione. https://pypi.python.org/pypi/ctds/ – Kerr

+0

Hai appena controllato il link che hai fornito. Penso sia molto buono. Fare un tentativo. Grazie. – Naufal