Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

to_sql pyodbc полето за броене е неправилно или синтактична грешка

По времето, когато беше зададен този въпрос, pandas 0.23.0 току-що беше пусната. Тази версия промени поведението по подразбиране на .to_sql() от извикване на DBAPI .executemany() метод за конструиране на конструктор на стойност на таблица (TVC), който би подобрил скоростта на качване чрез вмъкване на множество реда с един .execute() извикване на оператор INSERT. За съжаление този подход често надвишава ограничението на T-SQL от 2100 стойности на параметъра за съхранена процедура, което води до грешката, цитирана във въпроса.

Малко след това последващо издание на pandas добави method= аргумент към .to_sql() . По подразбиране – method=None – възстановено предишното поведение при използване на .executemany() , като указвате method="multi" ще каже на .to_sql() да използвате по-новия подход на TVC.

Приблизително по същото време беше пусната SQLAlchemy 1.3 и добави fast_executemany=True аргумент към create_engine() което значително подобри скоростта на качване с помощта на ODBC драйверите на Microsoft за SQL Server. С това подобрение, method=None се оказа, че е поне толкова бърз, колкото method="multi" като избягвате ограничението от 2100 параметъра.

Така че с текущите версии на pandas, SQLAlchemy и pyodbc, най-добрият подход за използване на .to_sql() с ODBC драйверите на Microsoft за SQL Server е да използвате fast_executemany=True и поведението по подразбиране на .to_sql() , т.е.

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

Това е препоръчителният подход за приложения, работещи под Windows, macOS и вариантите на Linux, които Microsoft поддържа за своя ODBC драйвер. Ако трябва да използвате FreeTDS ODBC, тогава .to_sql() може да се извика с method="multi" и chunksize= както е описано по-долу.

(Оригинален отговор)

Преди pandas версия 0.23.0, to_sql ще генерира отделен INSERT за всеки ред в 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'

Вероятно, за да подобри производителността, pandas 0.23.0 вече генерира конструктор на стойност на таблица за вмъкване на множество реда на извикване

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'

Проблемът е, че съхранените процедури на SQL Server (включително системни съхранени процедури като sp_prepexec ) са ограничени до 2100 параметъра, така че ако DataFrame има 100 колони, тогава to_sql може да вмъкне само около 20 реда наведнъж.

Можем да изчислим необходимия chunksize използвайки

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

Въпреки това, най-бързият подход все още вероятно ще бъде:

  • изхвърлете DataFrame в CSV файл (или подобен) и след това

  • накарайте Python да извика SQL Server bcp помощна програма за качване на този файл в таблицата.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да върнете всички ненадеждни ограничения CHECK в SQL Server (пример за T-SQL)

  2. Len() срещу datalength() в SQL Server 2005

  3. Производителност на SQL сървър TOP CPU заявка -1

  4. SQL Server - дефиниране на колона от тип XML с UTF-8 кодиране

  5. Връщане на редове, които съдържат небуквени и цифрови знаци в SQL Server