簡體   English   中英

如何使用 SQLAlchemy 定義沒有主鍵的表?

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

我有一張沒有primary key 而且我真的不想將此約束應用於此表。

SQLAlchemy 中,我通過以下方式定義了表類:

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

當我嘗試查詢此表時,我得到:

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

如何失去每個表必須有一個主鍵的約束?

我知道只有一種方法可以繞過 SQL Alchemy 中的主鍵約束 - 將特定的一列或多列作為主鍵映射到您的表,即使它們本身不是主鍵。 http://docs.sqlalchemy.org/en/latest/faq/ormconfiguration.html#how-do-i-map-a-table-that-has-no-primary-key

對此沒有適當的解決方案,但有解決方法:

解決方法 1

將參數 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

解決方法 2

只需在ORM 層上聲明一個新的虛擬列,而不是在實際的 DB 中 只需在 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

免責聲明:僅限 Oracle

Oracle 數據庫秘密地存儲稱為rowid東西來唯一地定義表中的每條記錄,即使該表沒有主鍵。 我通過構建我的 ORM 對象解決了我缺少主鍵的問題(這不是我造成的!),例如:

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

您可以通過運行查看rowid實際外觀(我相信這是一個十六進制值)

SELECT rowid FROM stupid_poorly_designed_table
GO

這是使用__mapper_args__合成 primary_key的示例。 因為表是面向時間序列的數據,所以不需要主鍵。 所有行都可以是具有(時間戳,對)元組的唯一地址。

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 測試

我知道這個線程很古老,但我花了太長時間才讓它工作而沒有分享它:)

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-首要的關鍵

一種方法:在 SQLAlchemy ORM 中,要映射到特定表,必須至少有一個列指定為主鍵列; 多列復合主鍵當然也是完全可能的。 這些列不需要被數據庫知道為主鍵列。 列只需要像主鍵一樣運行,例如行的不可為空的唯一標識符。

我的代碼:

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)

我找到的解決方案是向表中添加一個自動遞增的主鍵列,然后將其用作主鍵。 數據庫應該處理除此之外的所有其他事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM