1

我喜欢 sqlite 的清单类型/类型亲和力的想法:

http://www.sqlite.org/datatype3.html

本质上,如果我将列的关联性设置为“数字”,它将回避类型整数或浮点数以存储它们,但如果我愿意,仍然允许我存储字符串。在我看来,当我不确定要在其中存储哪些数据时,这是列的最佳“默认”类型。

所以我走了:

metadata = MetaData()
new_table = Table(table_name, metadata )
for col_name in column_headings:
    new_table.append_column(Column(col_name, 
                                   sqlite.NUMERIC, #this should duck-type numbers but can handle strings as well
                                   primary_key=col_name in primary_key_columns))
new_table.create(self.engine, checkfirst=False)

但是当我尝试在表中存储一些字符串值,例如“abc”时,sqlalchemy 失败了:

  File "[...]\sqlalchemy\processors.py", line 79, in to_float
    return float(value)
ValueError: invalid literal for float(): abc

嘘,嘶嘶声。那么,有什么办法可以说服 sqlalchemy 让 sqlite 进行打字?也许我可以使用 sqlalchemy.types 中的类型而不是 sqlachemy.dialects.sqlite?

[编辑:] 加分:我需要能够通过内省/反射访问表格。因此,使用 meta.reflect() 进行这项工作的某种方式会很棒!;-)

4

2 回答 2

1

好的,这就是我想出的:

根据 http://www.sqlalchemy.org/docs/reference/sqlalchemy/types.html#custom-types定义自定义列类型

文档和一些试验和错误的组合给了我这个:

class MyDuckType(sqlalchemy.types.TypeDecorator):
    """
    SQLALchemy custom column type, designed to let sqlite handle the typing 
    using 'numeric affinity' which intelligently handles both numbers and strings
    """
    impl = sqlite.NUMERIC

    def bind_processor(self, dialect):
        #function for type coercion during db write
        return None #ie pass value as-is, let sqlite do the typing

    def result_processor(self, dialect, coltype):
        #function for type coercion during db read
        return None #ie pass value as sqlite has stored it, should be ducktyped already

    def process_bind_param(self, value, dialect):
        #any changes to an individual value before store in DN
        return value

    def process_result_value(self, value, dialect):
        #any changes to an individual value after retrieve from DB
        return value

    def copy(self):
        #not quite sure what this is for
        return MyDuckType()

当前的 sqlalchemy 方言类型在 bind_processor 中返回 to_float,这就是我之前收到错误的原因。imvvho,这是一个错误。

对于我的奖励积分:在我的 metadata.reflect() 代码中手动将列类型设置为 MyDuckType:

def get_database_tables(engine):
    meta = MetaData()
    meta.reflect(bind=engine)
    tables = meta.raw_tables
    for tbl in tables.values():
        for col in tbl.c:
            col.type = MyDuckType()
    return tables

似乎对我有用。有什么建议/改进吗?

于 2010-06-15T15:21:50.083 回答
0

Essentially, if I set a column's affinity as 'numeric', it will duck type integers or floats to store them as such, but still allow me to store strings if I want to.

If you don't declare a column type at all, SQLite will let you store any type without performing conversions. This may be a better choice if you want to distinguish 123 from '123'.

于 2010-07-03T00:54:38.693 回答