缩写:
- 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
而不是INTERVAL
的Column
:
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?