首页 > 解决方案 > 如何修复多个外键

问题描述

我正在设置多个外键,但它显示错误

  from flask_sqlalchemy import SQLAlchemy     
  sql= SQLAlchemy(app)
  app.secret_key = os.urandom(24)
  app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql:///test'
  app.config['SECERET_KEY'] = 'RANDAM'

  class Users(sql.Model):

    __tablename__='users'

    id = sql.Column(sql.Integer, primary_key=True, nullable=False, 
                                                    default='')
    name = sql.Column(sql.String(25),nullable=False, default='')
    username = sql.Column(sql.String(25),nullable=False, default='')
    email = sql.Column(sql.String(25), primary_key=True,nullable=False, 
                                                    default='')
    password = sql.Column(sql.String(100),nullable=False, default='')
    reg_time = sql.func.current_timestamp()
    online =  sql.Column(sql.String(1),nullable=False, default='')

 class friendgroup(sql.Model):

    __tablename__='friendgroup'

    group_id = sql.Column(sql.Integer,sql.ForeignKey('users.id'),
            primary_key=True,nullable=False, default='')
    fg_name = sql.Column(sql.String(25), primary_key=True, nullable=False, 
                                                  default='')
    owner_email = sql.Column(sql.String(25),sql.ForeignKey('users.email'), 
             primary_key=True, nullable=False,default='')
    description = sql.Column(sql.String(25), nullable=False, default='')

 class belong(sql.Model):

    __tablename__ = 'belong'

    group_id=sql.Column(sql.Integer,sql.ForeignKey('friendgroup.group_id')
                     ,primary_key=True,nullable=False,default='')
    email = sql.Column(sql.String(25),sql.ForeignKey('users.email'),
               nullable=False, default='', primary_key=True)
    owner_email = sql.Column(sql.String(25),  
           sql.ForeignKey('friendgroup.owner_email'),nullable=False, 
                                       default='', primary_key=True)
    fg_name = sql.Column(sql.String(25), 
        sql.ForeignKey('friendgroup.fg_name'),nullable=False, default='', 
                                         primary_key=True)

 sql.create_all()
 app.run(debug=True)

我希望所有这些都将输入到数据库中,但它显示错误:

sqlalchemy.exc.OperationalError: (MySQLdb._exceptions.OperationalError) (1005, 'Can\'t create table test. friendgroup(errno: 150 "Foreign key constraint is wrongly forms")')

标签: pythonsqlalchemyflask-sqlalchemy

解决方案


当我运行时SHOW ENGINE INNODB STATUS,它在以下部分显示此错误LATEST FOREIGN KEY ERROR

在被引用的表中找不到被引用的列作为第一列出现的索引,或者表中的列类型与被引用的表的约束不匹配。请注意,使用创建的表中的 ENUM 和 SET 的内部存储类型发生了变化 >= InnoDB-4.1.12,并且旧表中的此类列不能被新表中的此类列引用。

我们可以忽略 and 的东西ENUMSET两者之间的类型定义是准确的,这样就剩下关于索引的问题了。

如果您添加index=True到列定义中Users.emailfriendgroup.fg_name它提供了一个索引,可用于 mysql 生成外键,并且您的表应该创建。

但是,我建议您重新考虑您的表的主键。您正在使用自动增量主键字段定义这些表中的每一个,但在复合主键中包含其他字段。你不需要这样做。如果您从主键中删除非自动增量列并在它们上添加唯一约束,那么您的所有问题都会消失。

此外,通过friendgroup.owner_email在主键或唯一约束中包含该字段意味着每个用户只能拥有一个朋友组。那是你要的吗?类似地,在表的主键中包含owner_emailand意味着只有一个用户可以属于特定用户拥有的任何组。fg_namebelong

如果有帮助,这就是我将这些模型放在一起的方式。它解决了您的外键问题并使用关系属性,而不是跨表复制电子邮件地址和组名等数据。

class Users(sql.Model):

    __tablename__ = "users"

    id = sql.Column(sql.Integer, primary_key=True)
    name = sql.Column(sql.String(25), nullable=False)
    username = sql.Column(sql.String(25), nullable=False)
    email = sql.Column(sql.String(25), unique=True, nullable=False)
    password = sql.Column(sql.String(100), nullable=False)
    reg_time = sql.Column(
        sql.TIMESTAMP, server_default=sql.func.current_timestamp()
    )
    online = sql.Column(sql.String(1), nullable=False, default="")


class friendgroup(sql.Model):

    __tablename__ = "friendgroup"

    group_id = sql.Column(
        sql.Integer, sql.ForeignKey("users.id"), primary_key=True
    )
    fg_name = sql.Column(sql.String(25), unique=True, nullable=False)
    owner_id = sql.Column(
        sql.Integer, sql.ForeignKey("users.id"), nullable=False
    )
    description = sql.Column(sql.String(25), nullable=False, default="")
    owner = sql.relationship("User")


class belong(sql.Model):

    __tablename__ = "belong"

    group_id = sql.Column(
        sql.Integer, sql.ForeignKey("friendgroup.group_id"), primary_key=True
    )
    user_id = sql.Column(
        sql.Integer, sql.ForeignKey("users.id"), primary_key=True
    )

    user = sql.relationship("User")
    group = sql.relationship("friendgroup")

推荐阅读