python 多字段外键关联

本文介绍了如何在Flask应用中使用SQLAlchemyORM进行多对多关系的设置,包括backref和外键约束的使用,并提供了查询特定路线关联行的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、参考https://docs.sqlalchemy.org/en/20/orm/backref.html

https://blog.csdn.net/u012206617/article/details/91436606 

https://www.codenong.com/43024464/ 

2、示例代码如下:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import and_, ForeignKeyConstraint
from sqlalchemy.orm import relationship


con_sql = 'mssql+pymssql://test:test@test/test?charset=utf8'
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = con_sql
app.config["SQLALCHEMY_ECHO"] = True
db = SQLAlchemy(app)


class ALines(db.Model):
    __tablename__ = "TRUCK_LINES"
    ASTN = db.Column(db.String(3), primary_key=True, nullable=False, info='')
    BSTN = db.Column(db.String(3), primary_key=True, nullable=False, info='')

    ROUTES = relationship(
        "ALineRoute",
        uselist=True,
        primaryjoin=(
            "and_(ALines.ASTN==ALineRoute.ASTN, ALines.BSTN==ALineRoute.BSTN)"
        ),
        backref="LINE",
    )


class ALineRoute(db.Model):
    __tablename__ = "TRUCK_LINES_ROUTES"
    ROUTE_ID = db.Column(db.BigInteger, primary_key=True, nullable=False, info='')
    ASTN = db.Column(db.String(3), db.ForeignKey('TRUCK_LINES.ASTN'), info='')
    BSTN = db.Column(db.String(3), db.ForeignKey('TRUCK_LINES.BSTN'), info='')

    ForeignKeyConstraint(('ALineRoute.ASTN', 'ALineRoute.BSTN'), ['ALineRoute.ASTN', 'ALineRoute.BSTN'])

    # LINE = relationship("ALines")


class TestRelationShip(object):

    def test_trucklines(self):
        route_entities = db.session.query(ALineRoute)\
            .filter(and_(ALineRoute.ASTN == 'TEST1',
                         ALineRoute.BSTN == 'TEST2')).all()
        entity, *_ = route_entities
        line = entity.LINE

        line_entities = db.session.query(ALines)\
            .filter(and_(ALines.ASTN == 'TEST1',
                         ALines.BSTN == 'TEST2')).all()
        entity, *_ = line_entities
        routes = entity.ROUTES

        return route_entities


if __name__ == "__main__":
    db_api = TestRelationShip()
    db_api.test_trucklines()


<think>我们正在讨论数据库中的主关系。用户希望了解字段与关联的定义、作用及使用方式。根据引用[1]和[2],我们可以总结如下:定义:-主(PrimaryKey):是表中唯一标识每一行记录的字段(或字段组合)。主的值必须是唯一的,且不能为空(NOTNULL)。例如,在用户表(tb_user)中,id字段可以作为主。-ForeignKey):是表中的某个字段(或字段组合),它不是本表的主,但它引用了另一个表的主用于建立两个表之间的关联关系。例如,在地址表(tb_address)中,有一个userid字段,它引用了用户表(tb_user)的主id。作用:1.数据完整性:约束确保只有另一个表的主中存在的值才能被插入到字段中,从而防止无效数据的产生。2.数据一致性:当主表中的数据被更新或删除时,约束可以定义相应的操作(如CASCADE、SETNULL等)以保持数据的一致性。3.建立表间关联是关系数据库实现表与表之间关系的重要手段,使得数据能够通过关联查询(如JOIN)被有效地组织和使用。使用方式:1.在创建表时定义约束:```sqlCREATETABLEtb_address(idINTPRIMARYKEY,useridINT,addressVARCHAR(255),FOREIGNKEY(userid)REFERENCEStb_user(id));```2.在已有表上添加约束:```sqlALTERTABLEtb_addressADDCONSTRAINTfk_useridFOREIGNKEY(userid)REFERENCEStb_user(id);```3.约束的动作:-ONDELETECASCADE:当主表中的记录被删除时,从表中相关联的记录也会被删除。-ONDELETESETNULL:当主表中的记录被删除时,从表中的字段设置为NULL(前提是该字段允许NULL)。-ONUPDATECASCADE:当主表中的主值被更新时,从表中对应的值也更新。4.删除约束:```sqlALTERTABLEtb_addressDROPFOREIGNKEYfk_userid;```根据引用[3],在应用框架(如Odoo)中,我们也可以使用关联字段。但需要注意,当被关联的字段是计算字段时,使用related属性可能会导致计算错误(因为环境变量传递问题),此时建议重新定义计算函数。注意事项:-字段的数据类型必须与所引用的主字段的数据类型匹配。-在插入或更新从表记录时,字段的值必须在主表的主中存在(或者为NULL,如果允许的话)。-约束可能会影响性能(特别是在大数据量时),因为每次修改字段都要检查主表的主。例子说明:假设有两个表:部门表(department)和员工表(employee)。-部门表的主是id,每个部门有唯一的id。-员工表有一个字段dept_id,它作为引用部门表的id。这样,每个员工都关联到一个存在的部门,保证了员工所属的部门是有效的。通过上述解释,用户应能理解主的基本定义、作用和使用方法。</think> ### 字段与关联的定义、作用及使用方式 #### 一、定义 1. **主(Primary Key)**[^1] 表中唯一标识每条记录的字段或字段组合,需满足: - **唯一性**:值在表中唯一 - **非空性**:不允许NULL值 ```sql CREATE TABLE users ( user_id INT PRIMARY KEY, -- 声明主 name VARCHAR(50) ); ``` 2. **(Foreign Key)**[^2] 从表中引用主表主的字段,需满足: - **数据类型匹配**:需与主字段类型相同 - **引用约束**:值必须存在于主表主中(或为NULL) ```sql CREATE TABLE orders ( order_id INT PRIMARY KEY, user_id INT, FOREIGN KEY (user_id) REFERENCES users(user_id) -- 声明 ); ``` #### 二、作用对比 | **特性** | 主 | | |-----------------|-------------------------|------------------------------| | **核心作用** | 唯一标识记录 | 建立表间关联 | | **数据完整性** | 实体完整性 | 参照完整性 | | **NULL值** | 绝对禁止 | 允许(需明确配置) | | **表角色** | 主表(父表)[^2] | 从表(子表)[^2] | | **数量限制** | 每表仅一个 | 每表可多个 | #### 三、使用方式 1. **约束声明** ```sql -- 建表时声明 CREATE TABLE child_table ( child_id INT PRIMARY KEY, parent_id INT, FOREIGN KEY (parent_id) REFERENCES parent_table(parent_id) ON DELETE CASCADE -- 级联删除 ); -- 后期添加约束 ALTER TABLE child_table ADD CONSTRAINT fk_parent FOREIGN KEY (parent_id) REFERENCES parent_table(parent_id); ``` 2. **数据操作示例** ```sql -- 合法操作(主存在) INSERT INTO orders VALUES (101, 1); -- 假设user_id=1存在于users表 -- 非法操作(违反约束) INSERT INTO orders VALUES (102, 99); -- user_id=99不存在 ``` 3. **约束动作**[^2] | 动作 | 效果说明 | |-------------------|----------------------------------------| | `ON DELETE CASCADE` | 主表记录删除时自动删除从表关联记录 | | `ON DELETE SET NULL`| 主表记录删除时从表设为NULL | | `ON UPDATE CASCADE` | 主值更新时自动更新从表关联字段 | #### 四、框架中的特殊应用[^3] 在Odoo等ORM框架中,关联可能通过声明实现: ```python class Order(models.Model): user_id = fields.Many2one('users') # 自动创建关联 ``` **注意**:当关联字段是计算字段时,避免直接引用`related`属性,可能导致上下文丢失和计算错误,建议重写计算函数。 #### 五、使用场景 1. 电商系统:订单表(关联用户表(主) 2. 内容管理:文章表(关联作者表(主) 3. 库存管理:库存记录(关联产品表(主) #### 六、注意事项 1. 确保字段索引以提高JOIN效率 2. 避免循环引用(表A引用表B,表B引用表A) 3.数据库操作时注意不同DBMS的实现差异 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值