sql >> データベース >  >> RDS >> Sqlserver

to_sqlpyodbcカウントフィールドが正しくないか構文エラー

    この質問がされた時点で、パンダ0.23.0がリリースされたばかりでした。そのバージョンは、.to_sql()のデフォルトの動作を変更しました DBAPIの呼び出しから.executemany() 単一の.execute()で複数の行を挿入することにより、アップロード速度を向上させるテーブル値コンストラクター(TVC)を構築するメソッド INSERTステートメントの呼び出し。残念ながら、そのアプローチは、ストアドプロシージャの2100パラメータ値というT-SQLの制限を超えることが多く、質問で引用されたエラーにつながりました。

    その後まもなく、パンダのその後のリリースでmethod=が追加されました .to_sql()への引数 。デフォルト– method=None.executemany()を使用する以前の動作を復元しました 、method="multi"を指定している間 .to_sql()に通知します 新しいTVCアプローチを使用します。

    同じ頃、SQLAlchemy 1.3がリリースされ、fast_executemany=Trueが追加されました。 create_engine()への引数 これにより、SQLServer用のMicrosoftのODBCドライバーを使用してアップロード速度が大幅に向上しました。この機能拡張により、method=None 少なくともmethod="multi"と同じくらい高速であることが証明されました 2100パラメータの制限を回避しながら。

    したがって、現在のバージョンのpandas、SQLAlchemy、およびpyodbcでは、.to_sql()を使用するための最良のアプローチです。 SQL Server用のMicrosoftのODBCドライバーでは、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、およびMicrosoftがODBCドライバー用にサポートしているLinuxバリアントで実行されているアプリに推奨されるアプローチです。 FreeTDS ODBCを使用する必要がある場合は、.to_sql() method="multi"で呼び出すことができます およびchunksize= 以下に説明するように。

    (元の回答)

    pandasバージョン0.23.0より前では、to_sql DataTableの行ごとに個別のINSERTを生成します:

    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にSQLServerのbcpを呼び出させます そのファイルをテーブルにアップロードするユーティリティ。



    1. フィールド名の周りにバッククォートを使用する

    2. MacOSXへのMySQLPythonのインストール

    3. Postgresqlテーブルの最大(使用可能な)行数

    4. MySQLのランク関数