Python SQLAlchemy:如何在多个insert语句中转换字符串值?

Python SQLAlchemy:如何在多个insert语句中转换字符串值?,python,sqlite,sqlalchemy,Python,Sqlite,Sqlalchemy,我有一个dict对象列表 data = [ {'id': 1, 'dt':'2002-01-02' }, {'id': 2, 'dt':'2014-01-15' }, {'id': 3, 'dt':'2005-10-20' } ] 以及使用sqlalchemy在sqlite中创建的一个表,如下所示 engine = create_engine(config.SQLALCHEMY_DATABASE_URI) metadata = MetaData() tbl1 = Table('t1', me

我有一个dict对象列表

data = [
{'id': 1, 'dt':'2002-01-02' },
{'id': 2, 'dt':'2014-01-15' },
{'id': 3, 'dt':'2005-10-20' }
]
以及使用sqlalchemy在sqlite中创建的一个表,如下所示

engine = create_engine(config.SQLALCHEMY_DATABASE_URI)
metadata = MetaData()

tbl1 = Table('t1', metadata,
                     Column('the_id', Integer, primary_key=True),
                     Column('the_dt', Date))

metadata.create_all(bind=engine)

stmt_insert = tbl1.insert().values(the_id=bindparam('id'), the_dt=bindparam('dt', type_=Date)

with engine.connect() as conn:
    conn.execute(stmt_insert, data)
这给了我以下错误:

sqlalchemy.exc.StatementError:(内置.TypeError)SQLite日期类型 仅接受Python日期对象作为输入


我应该为“type_uz”参数分配什么才能使绑定工作?

您需要将
dt
字符串转换为日期对象,例如:

import datetime
for item in data:
    item['dt'] = datetime.datetime.strptime(item['dt'], "%Y-%m-%d").date()
如果您不需要SQLAlchemy的ORM部分(无类/表映射)。最简单的方法是告诉SQLAlchemy您使用字符串而不是日期,如下所示:

tbl1 = Table('t1', metadata,
    Column('the_id', Integer, primary_key=True),
    Column('the_dt', String))
它将起作用,因为您的日期字符串使用ISO 8601格式(“%Y-%m-%d”)

但最佳做法是:

  • 从CSV读取记录
  • 将数据转换为Python对象(
    int
    date
    等)
  • 在数据库中插入数据
  • 转换可以在映射到表的类的构造函数中完成

    编辑一种“解决方案”

    我创建了一个带有
    字符串
    类型的“假”表,而不是
    日期

    fake_tbl1 = Table('t1', metadata,
                      Column('id', Integer, primary_key=True),
                      Column('dt', String))
    
    metadata.create_all(bind=engine)
    
    并按原样插入数据:

    data = [
        {'id': 1, 'dt': '2002-01-02'},
        {'id': 2, 'dt': '2014-01-15'},
        {'id': 3, 'dt': '2005-10-20'}
    ]
    
    stmt_insert = fake_tbl1.insert()
    
    with engine.connect() as conn:
        conn.execute(stmt_insert, data)
    
    然后我用所需的
    Date
    字段重新定义同一个表:

    tbl2 = Table('t1', metadata,
                 Column('id', Integer, primary_key=True),
                 Column('dt', Date),
                 extend_existing=True)
    
    以下是一个行选择:

    stmt_select = select([tbl2])
    
    with engine.connect() as conn:
        result = conn.execute(stmt_select)
    
    for row in result:
        print(row)
    
    您将获得:

    (1, datetime.date(2002, 1, 2))
    (2, datetime.date(2014, 1, 15))
    (3, datetime.date(2005, 10, 20))
    

    这适用于您的简单案例,但我不建议将其用于一般解决方案。

    是的,我已经这样做了。但是我想知道是否有某种方法可以使用sqlalchemy bindparam函数来实现,为什么不使用类/表映射呢?因为,我的要求是从csv文件导入数据,我不需要sqlalchemy的ORM部分。也只是单纯的好奇:哦,还有,看看。特别是“执行多个语句”这一主题。是的,我在发布后意识到;-)。嗯,你看过我编辑的一种“解决方案”吗?在sqlalchemy中,你可以使用func。示例-func.DATE(日期值为字符串)
    (1, datetime.date(2002, 1, 2))
    (2, datetime.date(2014, 1, 15))
    (3, datetime.date(2005, 10, 20))