SQLAlchemy 中的 PostgreSQL 多维数组

问题描述 投票:0回答:3

我在 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
);

这当然是不对的。我错过了什么?

python multidimensional-array sqlalchemy
3个回答
5
投票

我在这里回答这个问题,因为 Mike Bayer 在 sqlalchemy 用户上回答了这个问题。

请参阅 sqlalchemy-user 上的 thread,其中 Mike Bayer 回答了此问题。正如 Mike 所澄清的那样,正如我在阅读 PG 文档时错过的那样,PG 实际上并不强制执行数组维度,SQLA 也不会。因此,人们可以写

integer[][]
,但 PG 对待它与
integer[]
没有任何不同。特别是,PG 和 SQLA 都接受任何维度的数组表达式。我不知道为什么会这样。正如 Mike 所引用的,PG Arrays 文档

当前的实施并不强制执行声明的数量 尺寸也可以。特定元素类型的数组都是 无论尺寸或数量如何,均被视为同一类型 方面。因此,声明数组大小或维数 CREATE TABLE 只是文档;它不影响运行时 行为。

另请参阅他打开的。 看起来这是为了在 SQLA 级别强制执行维度。


4
投票

我试过这个

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中他们提到了。

但是,当前实现忽略任何提供的数组大小限制,即行为与未指定长度的数组相同。

因此,如果您没有声明任何内容,那么它将是您想要的数组。


0
投票

SQLAlchemy 此后引入了

dimensions=
kwarg,例如
Column('sample', postgresql.ARRAY(Integer, dimensions=2)

参见 https://docs.sqlalchemy.org/en/13/dialects/postgresql.html#sqlalchemy.dialects.postgresql.ARRAY.

© www.soinside.com 2019 - 2024. All rights reserved.