Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

to_sql pyodbc pole licznika nieprawidłowe lub błąd składni

W momencie, gdy zadano to pytanie, właśnie wydano pandy 0.23.0. Ta wersja zmieniła domyślne zachowanie .to_sql() od wywołania DBAPI .executemany() metoda konstruowania konstruktora wartości tabeli (TVC), który poprawiłby szybkość wysyłania poprzez wstawienie wielu wierszy za pomocą jednego .execute() wywołanie instrukcji INSERT. Niestety takie podejście często przekraczało limit 2100 wartości parametrów T-SQL dla procedury składowanej, co prowadziło do błędu cytowanego w pytaniu.

Wkrótce potem kolejne wydanie pand dodało method= argument do .to_sql() . Wartość domyślna — method=None – przywrócono poprzednie zachowanie przy użyciu .executemany() , określając method="multi" powie .to_sql() aby użyć nowszego podejścia TVC.

Mniej więcej w tym samym czasie wydano SQLAlchemy 1.3 i dodano fast_executemany=True argument do create_engine() co znacznie poprawiło prędkość wysyłania przy użyciu sterowników ODBC firmy Microsoft dla SQL Server. Dzięki temu ulepszeniu method=None okazał się co najmniej tak szybki jak method="multi" unikając limitu 2100 parametrów.

Tak więc z obecnymi wersjami pand, SQLAlchemy i pyodbc, najlepszym podejściem do używania .to_sql() ze sterownikami ODBC firmy Microsoft dla SQL Server jest użycie fast_executemany=True i domyślne zachowanie .to_sql() , czyli

connection_uri = (
    "mssql+pyodbc://scott:tiger^[email protected]/db_name"
    "?driver=ODBC+Driver+17+for+SQL+Server"
)
engine = create_engine(connection_uri, fast_executemany=True)
df.to_sql("table_name", engine, index=False, if_exists="append")

Jest to zalecane podejście w przypadku aplikacji działających w systemach Windows, macOS i wariantach systemu Linux obsługiwanych przez firmę Microsoft w przypadku sterownika ODBC. Jeśli potrzebujesz użyć FreeTDS ODBC, to .to_sql() można wywołać za pomocą method="multi" i chunksize= jak opisano poniżej.

(Oryginalna odpowiedź)

Przed wersją pandy 0.23.0, to_sql wygeneruje osobną WSTAWKĘ dla każdego wiersza w DataTable:

exec sp_prepexec @p1 output,N'@P1 int,@P2 nvarchar(6)',
    N'INSERT INTO df_to_sql_test (id, txt) VALUES (@P1, @P2)',
    0,N'row000'
exec sp_prepexec @p1 output,N'@P1 int,@P2 nvarchar(6)',
    N'INSERT INTO df_to_sql_test (id, txt) VALUES (@P1, @P2)',
    1,N'row001'
exec sp_prepexec @p1 output,N'@P1 int,@P2 nvarchar(6)',
    N'INSERT INTO df_to_sql_test (id, txt) VALUES (@P1, @P2)',
    2,N'row002'

Przypuszczalnie w celu poprawy wydajności pandas 0.23.0 generuje teraz konstruktor wartości tabeli do wstawiania wielu wierszy na wywołanie

exec sp_prepexec @p1 output,N'@P1 int,@P2 nvarchar(6),@P3 int,@P4 nvarchar(6),@P5 int,@P6 nvarchar(6)',
    N'INSERT INTO df_to_sql_test (id, txt) VALUES (@P1, @P2), (@P3, @P4), (@P5, @P6)',
    0,N'row000',1,N'row001',2,N'row002'

Problem polega na tym, że procedury składowane SQL Server (w tym procedury składowane systemowe, takie jak sp_prepexec ) są ograniczone do 2100 parametrów, więc jeśli DataFrame ma 100 kolumn, to to_sql może wstawić tylko około 20 wierszy na raz.

Możemy obliczyć wymagany chunksize za pomocą

# df is an existing DataFrame
#
# limit based on sp_prepexec parameter count
tsql_chunksize = 2097 // len(df.columns)
# cap at 1000 (limit for number of rows inserted by table-value constructor)
tsql_chunksize = 1000 if tsql_chunksize > 1000 else tsql_chunksize
#
df.to_sql('tablename', engine, index=False, if_exists='replace',
          method='multi', chunksize=tsql_chunksize)

Jednak najszybszym podejściem nadal będzie prawdopodobnie:

  • zrzucić DataFrame do pliku CSV (lub podobnego), a następnie

  • niech Python wywoła SQL Server bcp narzędzie do przesyłania tego pliku do tabeli.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Konwertuj „datetimeoffset” na „smalldatetime” w SQL Server (przykłady T-SQL)

  2. SQL Server DATEPART() vs DATENAME() — jaka jest różnica?

  3. Pobierz podciąg w SQL Server

  4. Jak ograniczyć NULL jako parametr do procedury składowanej SQL Server?

  5. Jakie są ograniczenia bazy danych?