我在 Debian squeeze 上使用 SQLAlchemy 0.6.3 和 PostgreSQL 8.4。我想要一张表,其中一列存储 PostgreSQL 中的某些内容,该表在 Python 中显示为整数列表或整数元组的列表。例如
((1,2), (3,4), (5,6,7))
在下面的示例中,该列是
model
。我认为合理的方法可能是将内容存储为 PG 二维表,在 PG 中看起来像integer[][]
。我不知道 SQLA 会以什么形式将其返回给 Python,但我希望它是类似于元组的元组。
但是,我不知道如何告诉 SQLA 给我一个二维整数数组。 sqlalchemy.dialects.postgresql.ARRAY
的
文档说
item_type – 该数组的项目的数据类型。注意 维数在这里无关紧要,所以多维数组如 INTEGER[][],被构造为 ARRAY(Integer),而不是 ARRAY(ARRAY(Integer)) 等。类型映射是即时计算出来的。
不幸的是,我不知道这意味着什么。类型映射如何即时解决这个问题?它需要创建正确的 DDL。 我对如何做到这一点的第一个也是唯一的猜测是
ARRAY(ARRAY(Integer))
。目前我有
crossval_table = Table(
name, meta,
Column('id', Integer, primary_key=True),
Column('created', TIMESTAMP(), default=now()),
Column('sample', postgresql.ARRAY(Integer)),
Column('model', postgresql.ARRAY(Integer)),
Column('time', Float),
schema = schema,
这将创建以下 DDL
CREATE TABLE crossval (
id integer NOT NULL,
created timestamp without time zone,
sample integer[],
model integer[],
"time" double precision
);
这当然是不对的。我错过了什么?
我在这里回答这个问题,因为 Mike Bayer 在 sqlalchemy 用户上回答了这个问题。
请参阅 sqlalchemy-user 上的 thread,其中 Mike Bayer 回答了此问题。正如 Mike 所澄清的那样,正如我在阅读 PG 文档时错过的那样,PG 实际上并不强制执行数组维度,SQLA 也不会。因此,人们可以写
integer[][]
,但 PG 对待它与 integer[]
没有任何不同。特别是,PG 和 SQLA 都接受任何维度的数组表达式。我不知道为什么会这样。正如 Mike 所引用的,PG Arrays 文档说
当前的实施并不强制执行声明的数量 尺寸也可以。特定元素类型的数组都是 无论尺寸或数量如何,均被视为同一类型 方面。因此,声明数组大小或维数 CREATE TABLE 只是文档;它不影响运行时 行为。
另请参阅他打开的票。 看起来这是为了在 SQLA 级别强制执行维度。
我试过这个
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
engine = create_engine('postgresql://:5432/test', echo=True)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.dialects import postgresql
Base = declarative_base()
from sqlalchemy import Column, Integer, String
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
sample = Column(postgresql.ARRAY(Integer))
Base.metadata.create_all(engine)
Session = sessionmaker(engine)
s = Session()
a = User()
a.name='test'
a.sample = [[1,2], [3,4]]
s.add(a)
s.commit()
我想这会解决你的问题。因为在doc中他们提到了。
但是,当前实现忽略任何提供的数组大小限制,即行为与未指定长度的数组相同。
因此,如果您没有声明任何内容,那么它将是您想要的数组。
SQLAlchemy 此后引入了
dimensions=
kwarg,例如Column('sample', postgresql.ARRAY(Integer, dimensions=2)
。
参见 https://docs.sqlalchemy.org/en/13/dialects/postgresql.html#sqlalchemy.dialects.postgresql.ARRAY.