首页 > 解决方案 > 将 python sqlalchemy 类转换为原始 SQL(使用外键创建表)

问题描述

我有一个 python 应用程序,我使用 sqlalchemy 和 posgreSQL。我已经在数据库中有一些数据并且不想重新创建它,所以我想向数据库添加一个表并保留所有数据(之前我为此使用了 alembic,但这次我想使用原始 SQL)。

这是我的新表,我想在 python 中将其添加到数据库中:

# User payed data
class UserPayData(Base):
    __tablename__ = 'userspaydata'
    id = Column(Integer, primary_key=True) 
    account_owner = Column(Text, nullable=False)
    IBAN = Column(Text, nullable=False)
    # Foreign Keys
    belongs_to_user_id = Column(Integer, ForeignKey('users.id'))
    payment_belongs_to_user_relation = relationship("User", back_populates="payment_belongs_to_user_addresses")

    def __init__(self, account_owner=None, IBAN=None):
        self.account_owner = account_owner
        self.IBAN = IBAN

    def get(self, id):
        if self.id == id:
            return self
        else:
            return None

    def __repr__(self):
        return '<%s(%r, %r, %r)>' % (self.__class__.__name__, self.id, self.account_owner, self.IBAN)

以下是users表格中的相关部分:

# Project
class User(UserMixin, Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    # etc...
    # Foreign Key payment
    payment_belongs_to_user_addresses = relationship('UserPayData', back_populates="payment_belongs_to_user_relation")

这是我要执行的原始 SQL:

CREATE TABLE 'userspaydata'
(
    account_owner TEXT NOT NULL,
    IBAN TEXT NOT NULL,
    belongs_to_user_id INT references users(id)
);

我发现了很多例子,有些是不同的。

我有几个问题:

我是否还必须创建主键?AFAIK,如果我没有定义主键,它将自动ID INT

关系不需要在数据库级别定义,它们是在应用程序级别定义的,还是我错了?如果我错了,我如何在原始 SQL 中定义关系?

我还没有提交 SQL 查询,语法是否正确?

标签: pythonsqlpostgresqlsqlalchemy

解决方案


我是否还必须创建主键

是的,如果您想使用 sqlalchemy 声明式映射来处理表,并且通常指定主键是一个好主意。

关系不需要在数据库级别定义,它们是在应用程序级别定义的,还是我错了?

Sqlalchemy 声明类中定义的外键映射到数据库外键约束。

同样,关系数据库中的关系是另一个好主意。除非您有特定的理由不这样做,否则请指定外键依赖项。

如果您没有在数据库中指定约束,您最终可能会得到损坏的数据。

如果您手动发出 DDL 语句,则可以指定外键约束。Postgres 文档中的外键

我还没有提交 SQL 查询,语法是否正确?

不,这是您的 DDL 语句的更正版本。

CREATE TABLE userspaydata (
  id INTEGER PRIMARY KEY,
  account_owner TEXT NOT NULL,
  IBAN TEXT NOT NULL,
  belongs_to_user_id INT references users(id) -- this is a FK constraint
);

请注意,id它不会自动递增。为了auto-increment id

id列定义更改为

-- postgrseql 10 & above
id INTEGER PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY
-- postgresql 9.6 & below
id SERIAL PRIMARY KEY

并将id列的 sqlalchemy 映射更改为

id = Column(Integer, primary_key=True, auto_increment=True)

推荐阅读