簡體   English   中英

sqlalchemy 在 postgres 中使用 inheritance

[英]sqlalchemy use of inheritance in postgres

為了學習 sqlalchemy(和 python),我正在嘗試復制一個已經存在的項目,但是在使用 postgres 找出 sqlalchemy 和 inheritance 時遇到了麻煩。

這是我們的 postgres 數據庫所做的一個示例(顯然,這是簡化的):

CREATE TABLE system (system_id SERIAL PRIMARY KEY, 
                     system_name VARCHAR(24) NOT NULL);
CREATE TABLE file_entry(file_entry_id SERIAL, 
                        file_entry_msg VARCHAR(256) NOT NULL, 
                        file_entry_system_name VARCHAR(24) REFERENCES system(system_name) NOT NULL);
CREATE TABLE ops_file_entry(CONSTRAINT ops_file_entry_id_pkey PRIMARY KEY (file_entry_id), 
     CONSTRAINT ops_system_name_check CHECK ((file_entry_system_name = 'ops'::bpchar))) INHERITS (file_entry);
CREATE TABLE eng_file_entry(CONSTRAINT eng_file_entry_id_pkey PRIMARY KEY (file_entry_id),
     CONSTRAINT eng_system_name_check CHECK ((file_entry_system_name = 'eng'::bpchar)) INHERITS (file_entry);
CREATE INDEX ops_file_entry_index ON ops_file_entry USING btree (file_entry_system_id);
CREATE INDEX eng_file_entry_index ON eng_file_entry USING btree (file_entry_system_id);

然后插入將使用觸發器完成,以便將它們正確插入到子數據庫中。 就像是:

CREATE FUNCTION file_entry_insert_trigger() RETURNS "trigger"
    AS $$
DECLARE 
BEGIN
     IF NEW.file_entry_system_name = 'eng' THEN
        INSERT INTO eng_file_entry(file_entry_id, file_entry_msg, file_entry_type, file_entry_system_name) VALUES (NEW.file_entry_id, NEW.file_entry_msg, NEW.file_entry_type, NEW.file_entry_system_name);
     ELSEIF NEW.file_entry_system_name = 'ops' THEN
        INSERT INTO ops_file_entry(file_entry_id, file_entry_msg, file_entry_type, file_entry_system_name) VALUES (NEW.file_entry_id, NEW.file_entry_msg, NEW.file_entry_type, NEW.file_entry_system_name);
     END IF;
     RETURN NULL;
 END;
 $$ LANGUAGE plpgsql;

總之,我有一個父表,其外鍵指向另一個表。 然后我有 2 個子表存在,並且插入是基於給定值完成的。 在我上面的示例中,如果 file_entry_system_name 是“ops”,則該行進入 ops_file_entry 表; 'eng' 進入 eng_file_entry_table。 我們的生產環境中有數百個子表,考慮到數據量,它確實加快了速度,所以我想保持這個相同的結構。 我可以查詢父表,只要我給它正確的“system_name”,它就會立即知道要查看哪個子表。

我的願望是用 sqlalchemy 來模擬這個,但我找不到任何例子可以說明 go 如此詳細。 我通過示例查看了由 sqlalchemy 生成的 sql 示例,我可以看出它在數據庫端沒有做任何類似的事情。

我能想到的最好的方法是:

class System(_Base):
    __tablename__ = 'system'
    system_id = Column(Integer, Sequence('system_id_seq'), primary_key = True)
    system_name = Column(String(24), nullable=False)
    def __init(self, name)
        self.system_name = name
class FileEntry(_Base):
    __tablename__ = 'file_entry'
    file_entry_id = Column(Integer, Sequence('file_entry_id_seq'), primary_key=True)
    file_entry_msg = Column(String(256), nullable=False)
    file_entry_system_name = Column(String(24), nullable=False, ForeignKey('system.system_name'))
    __mapper_args__ = {'polymorphic_on': file_entry_system_name}
    def __init__(self, msg, name)
        self.file_entry_msg = msg
        self.file_entry_system_name = name
class ops_file_entry(FileEntry):
    __tablename__ = 'ops_file_entry'
    ops_file_entry_id = Column(None, ForeignKey('file_entry.file_entry_id'), primary_key=True)
    __mapper_args__ = {'polymorphic_identity': 'ops_file_entry'}

最后,我錯過了什么? 我如何告訴 sqlalchemy 將插入到 FileEntry 的任何內容與系統名稱為“ops”的 go 關聯到“ops_file_entry”表? 我的理解有問題嗎?

對我應該做什么的一些見解會很棒。

您只需創建一個新的ops_file_entry實例(這不應該是OpsFileEntry嗎?),將其添加到 session 中,在刷新時,一行將插入到表file_entry以及表ops_file_entry中。

您不需要設置file_entry_system_name屬性,也不需要設置觸發器。

我真的不知道 python 或 sqlalchemy,但我想我會為過去的緣故試一試。 ;)

您是否嘗試過在應用程序級別設置自己的觸發器? 像這樣的東西可能會起作用:

from sqlalchemy import event, orm

def my_after_insert_listener(mapper, connection, target):
    # set up your constraints to store the data as you want
    if target.file_entry_system_name = 'eng'
        # do your child table insert
    elseif target.file_entry_system_name = 'ops'
        # do your child table insert
    #…

mapped_file_entry_class = orm.mapper(FileEntry, 'file_entry')
# associate the listener function with FileEntry,
# to execute during the "after_insert" hook
event.listen(mapped_file_entry_class, 'after_insert', my_after_insert_listener)

我不是很肯定,但我認為target (或者可能是mapper )應該包含正在插入的數據。

事件(尤其是 after_create)映射器可能會有所幫助。

暫無
暫無

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

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