【问题标题】:Computed text column as concat (sum of strings) of two other columns将文本列计算为其他两列的 concat(字符串总和)
【发布时间】:2021-11-03 14:36:48
【问题描述】:

我想要一个表格,其中有一对独特的 sourcesource_id。但我还需要单列唯一 id 以使 API 更简单。

我正在尝试将id 列作为其他两列的连接:

from sqlalchemy import Computed, Column, Integer, Text
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

class Product(Base):
    __tablename__ = "product"

    id = Column(Text, Computed("source || source_id"), primary_key=True)
    source = Column(Text, nullable=False)
    source_id = Column(Integer, nullable=False)
    name = Column(Text, nullable=True)

我第一次尝试使用contcat(),但它给了我错误:generation expression is not immutable

learned here 说它无法工作,我应该切换到||。但是|| 给了我同样的错误。如何解决?

以下是错误日志,其中包含生成的 SQL。

...
  File "/usr/local/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 717, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.ProgrammingError: (psycopg2.errors.InvalidObjectDefinition) generation expression is not immutable

[SQL:
CREATE TABLE product (
        id TEXT GENERATED ALWAYS AS (source || source_id) STORED NOT NULL,
        source TEXT NOT NULL,
        source_id INTEGER NOT NULL,
        name TEXT,
        CONSTRAINT pk_product PRIMARY KEY (id)
)

]
(Background on this error at: https://sqlalche.me/e/14/f405)

【问题讨论】:

  • 我会尝试在_init_方法中应用这个concat()。无论如何,这个问题很有趣,但我强烈建议您不要对 ID 使用这种方法。自动计算字段会更高效,如果需要,您可以添加计算字段。
  • @Christophe 你的意思是最好有:sourcesource_id 作为复合 PK 和 id 作为自动增量,不为空,唯一,整数?
  • 我什至不会创建复合 PK。您可以创建一个索引,但对于 PK,我真的更喜欢自动增量 id。在我的环境中,我们对 id 使用聚合,以建立“与源的显式链接”,这是一团糟

标签: python postgresql database-design sqlalchemy calculated-columns


【解决方案1】:

怎么样

CREATE TABLE product(
    CONCAT (source, source_id) AS "TEXT GENERATED ALWAYS",
    ...
)

直接在您的 SQL 语句中?

【讨论】:

  • 我不知道如何在 SQLAlchemy 中做到这一点
【解决方案2】:

source_id 显式转换为text 即可。

CREATE TABLE product
(
  id TEXT GENERATED ALWAYS AS (source || source_id::text) STORED NOT NULL,
  source TEXT NOT NULL,
  source_id INTEGER NOT NULL,
  name TEXT,
  CONSTRAINT pk_product PRIMARY KEY (id)
);

在 Python 中:

    id = Column(Text, Computed("source || source_id::text"), primary_key=True)

顺便说一句,id 不是多余的吗? CONSTRAINT pk_product PRIMARY KEY (source, source_id) 呢,即

    source = Column(Text, nullable=False, primary_key=True)
    source_id = Column(Integer, nullable=False, primary_key=True)

【讨论】:

  • 是的,id 是多余的,但它让我可以更轻松地进行 ForeignKeys 和 API 调用。虽然我会尝试切换到复合PK/复合FK,像你说的那样摆脱id,但这似乎是正确的做事方式。
  • 在尝试了复合 PK 并看到它的缺陷后,我决定使用 @Christophe 建议的单一自动增量 id PK
猜你喜欢
  • 2012-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-11
  • 2019-03-25
相关资源
最近更新 更多