2017-07-17 40 views
0

問題描述 -使用默認值SQLAlchemy批量插入缺失值

我想使用SQLAlchemy批量插入幾百行。該模式看起來像下面

all_scrips_tbl = Table('all_scrips_info', _METADATA, Column('security_isin', String(16), primary_key=True), Column('company_name', String(80)), Column('nse_traded', Boolean, default=False), Column('nse_start_date', Date, default=datetime.date(year=2001, day=1, month=1)), Column('bse_traded', Boolean, default=False), Column('bse_start_date', Date, default=datetime.date(year=2001, day=1, month=1)), ) 現在每個憑證可以是 - nse_traded=Truebse_traded=True或兩者nse_traded=True and bse_traded=True

所以,我必須插入語句一樣 -

對於只有nse_traded=True ins = t.insert().values(security_isin=nstock.isin, company_name=nstock.name, nse_traded=True, nse_start_date=nstart_date, )

證券

對於只有bse_traded=True -

ins = t.insert().values(security_isin=bstock.isin, company_name=bstock.name, bse_traded=True, bse_start_date=bstart_date)

,並相應地爲nse_traded=Truebse_traded=True

我想批量插入這些語句。因此,像values().compile從創建語句的默認值是非常有用的,這樣我就可以使用下面 -

conn.execute(all_scrips_info.insert() , [ {}, {} ]) 凡類型的字典進行填充默認爲合適?

我也看過this的問題,但這與我的要求稍有不同。有一個old question on google groups這與我的要求相似。但是,sqlalchemy版本比較老,加上答案不是很容易理解。

我是否錯過了一些非常明顯的東西?

+0

我是否理解正確,你必須在有三組記錄的數據集: (1) nse_traded,(2)bse_traded和(3)nse_traded和bse_traded,並且您想批量插入這些記錄? –

+0

是的,這是正確的 - 我也默認定義(如適用)。我在做什麼,現在是使用'values'產生'insert'報表和像'執行(插入)'循環運行它們。我想用'執行(插入,[{},{}])'這裏的時候我不'insert.values'明確地使用它們使用默認值。 – gabhijit

回答

0

下面我提供瞭如何可以更容易地從一個CSV文件中的數據插入使用SQLAlchemy的數據庫的簡單例子。這裏的默認值是創建的日期。在init函數中,您可以添加更多邏輯......創建對象時應用此邏輯。

我想指出其他方法可用。例如,見SQLAlchemy的文檔:http://docs.sqlalchemy.org/en/latest/orm/persistence_techniques.html#bulk-operations

例子:

import csv 
from io import StringIO 
from sqlalchemy import Column, Integer, String, DateTime 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy import create_engine 
from sqlalchemy.orm import sessionmaker 
from datetime import datetime 

# Setting up model 

Base = declarative_base() 


class Car(Base): 
    __tablename__ = 'car' 

    id = Column('id', Integer, primary_key=True) 
    created = Column('created', DateTime, default=datetime.now()) 
    brand = Column(String(250)) 
    nr_gears = Column('nr_gears', Integer) 

    def __init__(self, brand, nr_gears): 
     self.brand = brand 
     self.nr_gears = nr_gears 

     # You can place logic,conditions here when creating the objects. Now only use of default date - creation 

    def __repr__(self): 
     return '{created}\t{brand} (nr of gears: {nr_gears})'.format(
      created=datetime.strftime(self.created, '%d/%m/%Y'), brand=self.brand, nr_gears=self.nr_gears) 


engine = create_engine('sqlite:///') 
session = sessionmaker() 
session.configure(bind=engine) 
ex_ses = session() 
Base.metadata.create_all(engine) 

# Reading in some dummy data 

csv_data = \ 
    '''Audi,5 
    BMW,5 
    Mercedes-Benz,5 
    Opel,5 
    Porsche,6 
    Volkswagen,5 
    Acura,5 
    Datsun,6 
    Honda,6 
    Infiniti,5 
    Isuzu,6 
    Lexus,5 
    Mazda,5 
    Mitsubishi,5 
    Nissan,5 
    Suzuki,6 
    Toyota,6 
    Subaru,6''' 

with StringIO(csv_data) as car_csv: 
    cars_data = [] 
    readCSV = csv.reader(car_csv, delimiter=',') 
    for row in readCSV: 
     # Add data to the session. 
     ex_ses.add(Car(brand=row[0], nr_gears=row[1])) 

ex_ses.commit() 

# Query 
cars = (ex_ses.query(Car).all()) 
print('Created\t\tBrand (nr of gears)') 
print('-' * 45) 
for car in cars: 
    print(car) 

# output: 
''' 
Created  Brand (nr of gears) 
--------------------------------------------- 
18/07/2017 Audi (nr of gears: 5) 
18/07/2017 BMW (nr of gears: 5) 
18/07/2017 Mercedes-Benz (nr of gears: 5) 
18/07/2017 Opel (nr of gears: 5) 
18/07/2017 Porsche (nr of gears: 6) 
18/07/2017 Volkswagen (nr of gears: 5) 
18/07/2017 Acura (nr of gears: 5) 
18/07/2017 Datsun (nr of gears: 6) 
18/07/2017 Honda (nr of gears: 6) 
18/07/2017 Infiniti (nr of gears: 5) 
18/07/2017 Isuzu (nr of gears: 6) 
18/07/2017 Lexus (nr of gears: 5) 
18/07/2017 Mazda (nr of gears: 5) 
18/07/2017 Mitsubishi (nr of gears: 5) 
18/07/2017 Nissan (nr of gears: 5) 
18/07/2017 Suzuki (nr of gears: 6) 
18/07/2017 Toyota (nr of gears: 6) 
18/07/2017 Subaru (nr of gears: 6) 
''' 

希望這有助於。基於我已經擴大低於汽車類的評論:

編輯。如果檔位數量丟失......則使用默認值9。當然,這是一個有限的例子,但(我希望)顯示,通過默認值工作的可能性......

class Car(Base): 
    __tablename__ = 'car' 

    id = Column('id', Integer, primary_key=True) 
    created = Column('created', DateTime, default=datetime.now()) 
    brand = Column(String(250)) 
    nr_gears = Column('nr_gears', Integer,default=None) 

    def __init__(self, brand, nr_gears): 
     self.brand = brand 

     if nr_gears is None or nr_gears == '': 
      nr_gears = 9 

     self.nr_gears = nr_gears 

     # You can place logic,conditions here when creating the objects. Now only use of default date - creation 

    def __repr__(self): 
     return '{created}\t{brand} (nr of gears: {nr_gears})'.format(
      created=datetime.strftime(self.created, '%d/%m/%Y'), brand=self.brand, nr_gears=self.nr_gears) 
+0

您的解決方案有幾個問題,因此無法接受它。 1.想象一下,如果您的CSV文件中某些模型沒有「齒輪」條目,並且您的DDL中提到它爲5,那麼無論何時我沒有指定它,請使用5(「默認」屬性的目的)。 SA批量插入的問題是 - 語法'execte(table.insert,[{dict of values}]'強制所有字典的大小相同。如果我的數據確實來自一個CSV文件,我可能會寫這個 - 它來自兩套(從一些不同的地方填充)。 – gabhijit

+0

不管SA批量插入的問題。關於如何爲缺失值定義和插入默認值的進一步問題(如果該值完全從CSV ... 0中丟失,這可以在init中實現,如果這個(我對問題的解釋)是正確的我會更新這個例子。 –

+0

是的 - 但我不想在SA之外進行沉重的舉動 - 我只是在想如果我錯過了一個更簡單的方法,並且SA已經提供了這個方法。 – gabhijit