簡體   English   中英

使用 to_sql 將 Pandas dataframe 中的數據批量插入 Sybase 數據庫表失敗

[英]Failing bulk insert data from Pandas dataframe into Sybase database table using to_sql

我下面代碼的目的是從一個 restful 服務中獲取數據,對其進行規范化,將其存儲在 dataframe 中,並使用必要的列,然后最后使用 Pandas 的to_sql將其加載到 Sybase 表中。

錯誤:

文件“C:\Program Files\Anaconda3\lib\site-packages\sqlalchemy\engine\default.py”,第 467 行,在 do_executemany cursor.executemany(語句,參數)sqlalchemy.exc.ProgrammingError:( '42000', "[42000] [Sybase][ODBC Driver][Adaptive Server Enterprise]',' 附近的語法不正確。\n (102) (SQLExecDirectW)") [SQL: 'INSERT INTO dbo.contract_test ("CONTRACT_ID" , "EXCHANGE_ID", "CURRENCY", "TRADING_CODE") VALUES (?, ?, ?, ?)'] [參數: (('0050/TAIEX', 'TAIEX', 'TWD', 0), ('035420 /KORE', 'KORE', 'KRW', 0), ('0TL/LIF', 'LIF', 'NOK', 1), ('100FTSE/LIF', 'LIF', 'GBP', 0) , ('101FTSE/LIF', 'LIF', 'GBP', 0), ('10STAT/OM', 'OM', 'SEK', 0), ('10TB/KFX', 'KFX', 'KRW ', 0), ('10TBA/KFX', 'KFX', 'KRW', 0)...顯示 4525 個總綁定參數集中的 10 個... ('ZURF/DTB', 'DTB', 'CHF' , 0), ('ZX/NYCE', 'NYCE', 'USD', 0))]

進程以退出代碼 1 結束

代碼:

from sqlalchemy.engine.url import *               
from sqlalchemy.connectors.pyodbc import *             
from sqlalchemy import create_engine                       
import urllib.request as request                  
import json                         
import pandas as pd                      
from pandas.io.json import json_normalize, DataFrame      
           
response = request.urlopen('http://tfsdscsw5XX/mdsclass/CONTFUTURES--O.json')            
output=response.read()                              
data=json.loads(output)           
df=json_normalize(data)                           
df1=(df[['CONTRACT_ID','EXCHANGE_ID','CURRENCY','TRADING_CODE']])                
df2=pd.DataFrame(df1)           
print(df2)                
print(df2.CONTRACT_ID)          
            
connector =  PyODBCConnector()                 
url = make_url("sybase+pyodbc://myhost/mydatabase?driver=Adaptive Server Enterprise&port=2306")              
print(connector.create_connect_args(url))                         
engine=create_engine(url)

#it is failing here**
df2.to_sql("contract_test",engine,index=False,if_exists="append",schema="dbo")   

response.close()               

dataframe df2中的數據樣本:

      CONTRACT_ID EXCHANGE_ID CURRENCY  TRADING_CODE
0      0050/TAIEX       TAIEX      TWD             0
1     035420/KORE        KORE      KRW             0
2         0TL/LIF         LIF      NOK             1
3     100FTSE/LIF         LIF      GBP             0
4     101FTSE/LIF         LIF      GBP             0

表contract_test定義:

CREATE TABLE contract_test (
    CONTRACT_ID char(12) NOT NULL,
    EXCHANGE_ID char(12),
    CURRENCY char(4) NOT NULL,
    TRADING_CODE smallint
) 
GO

請幫助如何解決這個問題? 我被困在這里。

您的問題可能只是 Python 數據庫 API 不兼容。 Pandas 的to_sql實際上是從pyodbc運行executemany()調用。 該模塊更普遍地與 SQL 服務器一起使用,尤其是在與 SQLAlchemy 一起實現時。 但是,不完全支持與 Sybase 的集成。 如 SQLAlchemy Sybase文檔頁面所述:

筆記

目前不支持 SQLAlchemy 中的 Sybase 方言。 它沒有在持續集成中進行測試,並且可能存在許多當前未處理的問題和警告。 考慮改用外部方言。

具體來說, executemany似乎正在運行多個VALUES行插入,SQL 服務器支持但 Sybase 不支持(即使這兩種方言都是 TSQL 的變體,具有已知的連接歷史):

INSERT INTO dbo.contract_test ("CONTRACT_ID", "EXCHANGE_ID", "CURRENCY", "TRADING_CODE") 
VALUES ('0050/TAIEX', 'TAIEX', 'TWD', 0), 
       ('035420/KORE', 'KORE', 'KRW', 0), 
       ('0TL/LIF', 'LIF', 'NOK', 1), 
...

相反,Sybase 需要具有多個INSERT INTO調用的經典 ANSI-SQL:

INSERT INTO dbo.contract_test ("CONTRACT_ID", "EXCHANGE_ID", "CURRENCY", "TRADING_CODE") 
VALUES ('0050/TAIEX', 'TAIEX', 'TWD', 0) 
INSERT INTO dbo.contract_test ("CONTRACT_ID", "EXCHANGE_ID", "CURRENCY", "TRADING_CODE") 
VALUES ('035420/KORE', 'KORE', 'KRW', 0)
INSERT INTO dbo.contract_test ("CONTRACT_ID", "EXCHANGE_ID", "CURRENCY", "TRADING_CODE") 
VALUES ('0TL/LIF', 'LIF', 'NOK', 1)
...

要解決此問題,請考慮使用通過DataFrame.to_numpy()使用數據幀行列表的參數的直接 SQLAlchemy executemany調用,而不是 Pandas 方便的to_sql方法。 下面假設contract_test表總是預先存在。

engine = create_engine(url)
sql = """INSERT INTO dbo.contract_test ("CONTRACT_ID", "EXCHANGE_ID", "CURRENCY", "TRADING_CODE") 
         VALUES (?, ?, ?, ?)"""

with engine.connect() as connection:
    result = connection.execute(sql, df2.to_numpy().tolist())

如果上面仍然面臨同樣的問題,請集成一個 for 循環:

with engine.connect() as connection:
    for row in df2.to_numpy().tolist():
        result = connection.execute(sql, row)

外部 SAP ASE (Sybase) 方言現在是 Sybase 推薦的 SQLAlchemy 方言,如果使用 SAP ASE ODBC 驅動程序,它確實支持fast_executemany

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM