简体   繁体   English

如何使用 SQLAlchemy 定义没有主键的表?

[英]How to define a table without primary key with SQLAlchemy?

I have a table that does not have a primary key .我有一张没有primary key And I really do not want to apply this constraint to this table.而且我真的不想将此约束应用于此表。

In SQLAlchemy , I defined the table class by:SQLAlchemy 中,我通过以下方式定义了表类:

class SomeTable(Base):
  __table__ = Table('SomeTable', meta, autoload=True, autoload_with=engine)

When I try to query this table, I got:当我尝试查询此表时,我得到:

ArgumentError: Mapper Mapper|SomeTable|SomeTable could not assemble any primary key columns for mapped table 'SomeTable'.

How to loss the constraint that every table must have a primary key?如何失去每个表必须有一个主键的约束?

There is only one way that I know of to circumvent the primary key constraint in SQL Alchemy - it's to map specific column or columns to your table as a primary keys, even if they aren't primary key themselves.我知道只有一种方法可以绕过 SQL Alchemy 中的主键约束 - 将特定的一列或多列作为主键映射到您的表,即使它们本身不是主键。 http://docs.sqlalchemy.org/en/latest/faq/ormconfiguration.html#how-do-i-map-a-table-that-has-no-primary-key . http://docs.sqlalchemy.org/en/latest/faq/ormconfiguration.html#how-do-i-map-a-table-that-has-no-primary-key

There is no proper solution for this but there are workarounds for it:对此没有适当的解决方案,但有解决方法:

Workaround 1解决方法 1

Adding parameter primary_key to the existing column that is not having a primary key will work.将参数 primary_key 添加到没有主键的现有列将起作用。

class SomeTable(Base):
    __table__ = 'some_table'
    some_other_already_existing_column = Column(..., primary_key=True) # just add primary key to it whether or not this column is having primary key or not

Workaround 2解决方法 2

Just declare a new dummy column on the ORM layer, not in actual DB .只需在ORM 层上声明一个新的虚拟列,而不是在实际的 DB 中 Just define in SQLalchemy model只需在 SQLalchemy 模型中定义

class SomeTable(Base):
    __table__ = 'some_table'
    column_not_exist_in_db = Column(Integer, primary_key=True) # just add for sake of this error, dont add in db

Disclaimer: Oracle only免责声明:仅限 Oracle

Oracle databases secretly store something called rowid to uniquely define each record in a table, even if the table doesn't have a primary key. Oracle 数据库秘密地存储称为rowid东西来唯一地定义表中的每条记录,即使该表没有主键。 I solved my lack of primary key problem (which I did not cause!) by constructing my ORM object like:我通过构建我的 ORM 对象解决了我缺少主键的问题(这不是我造成的!),例如:

class MyTable(Base)
    __tablename__ = 'stupid_poorly_designed_table'
    
    rowid = Column(String, primary_key=True)
    column_a = Column(String)
    column_b = Column(String)
    ...

You can see what rowid actually looks like (it's a hex value I believe) by running您可以通过运行查看rowid实际外观(我相信这是一个十六进制值)

SELECT rowid FROM stupid_poorly_designed_table
GO

Here is an example using __mapper_args__ and a synthetic primary_key .这是使用__mapper_args__合成 primary_key的示例。 Because the table is time-series oriented data, there is no need for a primary key.因为表是面向时间序列的数据,所以不需要主键。 All rows can be unique addresses with a (timestamp, pair) tuple.所有行都可以是具有(时间戳,对)元组的唯一地址。

class Candle(Base):

    __tablename__ = "ohlvc_candle"

    __table_args__ = (
        sa.UniqueConstraint('pair_id', 'timestamp'),
    )

    #: Start second of the candle
    timestamp = sa.Column(sa.TIMESTAMP(timezone=True), nullable=False)

    open = sa.Column(sa.Float, nullable=False)
    close = sa.Column(sa.Float, nullable=False)
    high = sa.Column(sa.Float, nullable=False)
    low = sa.Column(sa.Float, nullable=False)
    volume = sa.Column(sa.Float, nullable=False)

    pair_id = sa.Column(sa.ForeignKey("pair.id"), nullable=False)
    pair = orm.relationship(Pair,
                        backref=orm.backref("candles",
                                        lazy="dynamic",
                                        cascade="all, delete-orphan",
                                        single_parent=True, ), )

    __mapper_args__ = {
        "primary_key": [pair_id, timestamp]
    }

MSSQL Tested MSSQL 测试

I know this thread is ancient but I spent way too long getting this to work to not share it :)我知道这个线程很古老,但我花了太长时间才让它工作而没有分享它:)

from sqlalchemy import Table, event
from sqlalchemy.ext.compiler import compiles
from sqlalchemy import Column
from sqlalchemy import Integer

class RowID(Column):
    pass


@compiles(RowID)
def compile_mycolumn(element, compiler, **kw):
    return "row_number() OVER (ORDER BY (SELECT NULL))"


@event.listens_for(Table, "after_parent_attach")
def after_parent_attach(target, parent):
    if not target.primary_key:
        # if no pkey create our own one based on returned rowid
        # this is untested for writing stuff - likely wont work
        logging.info("No pkey defined for table, using rownumber %s", target)
        target.append_column(RowID('row_id', Integer, primary_key=True))

https://docs-sqlalchemy-org.translate.goog/en/14/faq/ormconfiguration.html?_x_tr_sl=auto&_x_tr_tl=ru&_x_tr_hl=ru#how-do-i-map-a-table-that-has-no-primary-key https://docs-sqlalchemy-org.translate.goog/en/14/faq/ormconfiguration.html?_x_tr_sl=auto&_x_tr_tl=ru&_x_tr_hl=ru#how-do-i-map-a-table-that-has-no-首要的关键

One way from there: In SQLAlchemy ORM, to map to a specific table, there must be at least one column designated as the primary key column;一种方法:在 SQLAlchemy ORM 中,要映射到特定表,必须至少有一个列指定为主键列; multi-column composite primary keys are of course also perfectly possible.多列复合主键当然也是完全可能的。 These columns do not need to be known to the database as primary key columns.这些列不需要被数据库知道为主键列。 The columns only need to behave like a primary key, such as a non-nullable unique identifier for a row.列只需要像主键一样运行,例如行的不可为空的唯一标识符。

my code:我的代码:

from ..meta import Base, Column, Integer, Date


class ActiveMinutesByDate(Base):
    __tablename__ = "user_computer_active_minutes_by_date"

    user_computer_id = Column(Integer(), nullable=False, primary_key=True)
    user_computer_date_check = Column(Date(), default=None,  primary_key=True)
    user_computer_active_minutes = Column(Integer(), nullable=True)

The solution I found is to add an auto-incrementing primary key column to the table, then use that as your primary key.我找到的解决方案是向表中添加一个自动递增的主键列,然后将其用作主键。 The database should deal with everything else beyond that.数据库应该处理除此之外的所有其他事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM