SQLAlchemy 元数据列类型,Postgresql 间隔小时到秒



缩写:

  • pg = postgresql
  • SA = sqlalchemy

环境:

  • 第9.6.2页
  • SA 1.1.9

我有一个表,其中有一列使用字段限制间隔类型:

interval hour to second(0)

我有一个带字符串的引擎'postgresql://....'.当我执行时:

meta = sa.MetaData(connection)  
meta.reflect()

我得到:

SAWarning: Did not recognize type 'interval hour to second' of column 'Visit duration'
(attype, name))

以及一个带有NullType而不是INTERVALColumn

Column('Visit duration', NullType(), table=<rep>)

怎么了?

出于某种原因,SQLAlchemy 中的 Postgresql 方言仅映射字段受限间隔类型的子集:

ischema_names = {
...
'interval': INTERVAL,
'interval year to month': INTERVAL,
'interval day to second': INTERVAL,
...
}

这两个是很久以前添加的,确切地说是在 2009 年。给定一个表:

create table test (
id serial primary key,
duration interval hour to second,
duration2 interval year to month
);

SQLAlchemy 很乐意将第 2 个持续时间列映射到INTERVAL类型,但正如您已经注意到的,第一个持续时间列NullType,因为:

NullType用作无法确定类型的默认类型,包括:

  • 在表反射期间,当方言无法识别列的类型时

另一方面,这不会完全阻止您使用该列:

NullType可以在 SQL 表达式调用中使用而不会出现问题,只是在表达式构造级别或绑定参数/结果处理级别没有任何行为。 如果要求编译器呈现类型本身(例如,在cast()操作或架构创建操作(如MetaData.create_all()CreateTable构造调用的操作),则NullType将导致CompileError

例如,对于数据:

[local]:5432 user@sopython=> insert into test (duration) values ('1 hour'::interval);
INSERT 0 1
[local]:5432 user@sopython*=> insert into test (duration) values ('34 minutes 1 second'::interval);
INSERT 0 1
[local]:5432 user@sopython*=> commit;

在 Python 中:

In [2]: metadata.reflect()
/home/user/Work/SO/lib/python3.5/site-packages/sqlalchemy/dialects/postgresql/base.py:2517: SAWarning: Did not recognize type 'interval hour to second' of column 'duration'
(attype, name))
In [3]: engine.execute(metadata.tables['test'].select()).fetchall()
Out[3]: 
[(1, datetime.timedelta(0, 3600), None),
(2, datetime.timedelta(0, 2041), None)]

但是,您无法使用反射Table实例重新创建表:

In [4]: from sqlalchemy.schema import CreateTable
In [5]: from sqlalchemy.dialects import postgresql
In [6]: print(CreateTable(metadata.tables['test']).compile(dialect=postgresql.dialect()))
---------------------------------------------------------------------------
CompileError                              Traceback (most recent call last)
...
CompileError: (in table 'test', column 'duration'): Can't generate DDL for NullType(); did you forget to specify a type on this Column?

最新更新