【问题标题】:FOREIGN KEY constraint failed in Web2pyWeb2py 中的 FOREIGN KEY 约束失败
【发布时间】:2018-11-06 23:34:45
【问题描述】:

我在 tables.py 中有两个表格 -

db.define_table('spr_details',
Field('SPR_name', 'string', unique=True, notnull=True),
Field('Object_location',notnull=True),
Field('NSK_System',notnull=True,),
primarykey = ['SPR_name'],migrate=True)

db.define_table('my_master_table',
Field('Test_id',notnull=True),
Field('Test_suite',notnull=True),
Field('Test_category',notnull=True),
Field('Test_unit',notnull=True),
Field('Test_case',notnull=True),
Field ('Applicability', db.spr_details,'string'),migrate=True)

我在 spr_details 表中插入了一行。现在,当我在 my_master 表中插入记录时,我从适用性下拉列中选择先前插入的值。但是在提交时,我得到了

外键约束失败错误。

下面是堆栈跟踪 -

Stack trace

Traceback

 Traceback (most recent call last):
  File "C:\Users\pandeyar\Downloads\web2py_src\web2py\gluon\restricted.py", line 219, in restricted
    exec(ccode, environment)
  File "C:/Users/pandeyar/Downloads/web2py_src/web2py/applications/JDBC_E2E/controllers/default.py", line 183, in <module>
  File "C:\Users\pandeyar\Downloads\web2py_src\web2py\gluon\globals.py", line 419, in <lambda>
    self._caller = lambda f: f()
  File "C:/Users/pandeyar/Downloads/web2py_src/web2py/applications/JDBC_E2E/controllers/default.py", line 99, in admin
    user_signature=False,
  File "C:\Users\pandeyar\Downloads\web2py_src\web2py\gluon\sqlhtml.py", line 3338, in smartgrid
    user_signature=user_signature, **kwargs)
  File "C:\Users\pandeyar\Downloads\web2py_src\web2py\gluon\sqlhtml.py", line 2534, in grid
    onsuccess=oncreate)
  File "C:\Users\pandeyar\Downloads\web2py_src\web2py\gluon\html.py", line 2300, in process
    self.validate(**kwargs)
  File "C:\Users\pandeyar\Downloads\web2py_src\web2py\gluon\html.py", line 2238, in validate
    if self.accepts(**kwargs):
  File "C:\Users\pandeyar\Downloads\web2py_src\web2py\gluon\sqlhtml.py", line 1965, in accepts
    self.vars.id = self.table.insert(**fields)
  File "C:\Users\pandeyar\Downloads\web2py_src\web2py\gluon\packages\dal\pydal\objects.py", line 753, in insert
    ret = self._db._adapter.insert(self, row.op_values())
  File "C:\Users\pandeyar\Downloads\web2py_src\web2py\gluon\packages\dal\pydal\adapters\base.py", line 486, in insert
    raise e
  File "C:\Users\pandeyar\Downloads\web2py_src\web2py\gluon\packages\dal\pydal\adapters\base.py", line 481, in insert
    self.execute(query)
  File "C:\Users\pandeyar\Downloads\web2py_src\web2py\gluon\packages\dal\pydal\adapters\__init__.py", line 67, in wrap
    return f(*args, **kwargs)
  File "C:\Users\pandeyar\Downloads\web2py_src\web2py\gluon\packages\dal\pydal\adapters\base.py", line 412, in execute
    rv = self.cursor.execute(command, *args[1:], **kwargs)
sqlite3.IntegrityError: FOREIGN KEY constraint failed

任何帮助都会非常有帮助。

【问题讨论】:

    标签: python web2py


    【解决方案1】:

    请参阅keyed tables 上的文档(即主键不是默认自增整数 ID 字段的表),因为spr_details 就是这样一个表。

    注意,您的参考字段定义存在两个问题:

        Field('Applicability', db.spr_details, 'string')
    

    首先,如文档中所述,在引用键控表时,Field()type 参数的格式必须是 'reference tablename.fieldname',而不是 db.tablename。其次,您没有单独指定引用字段的类型(即,您不应将'string' 作为第三个参数传递给Field(),因为第三个参数是length 参数,而不是type -- type 是根据引用字段的类型推断出来的)。所以,字段定义应该是:

        Field('Applicability', 'reference spr_details.SPR_name')
    

    注意,由于您当前对 Applicability 字段的定义不正确,该字段将变为整数字段(因为它希望在外表中存储对整数 ID 字段的引用)。如果你尝试插入一个整数,你会得到一个外键约束失败错误,如果你试图插入一个字符串,你会得到一个关于在应该int 的地方插入一个字符串的错误。如果您使用如上所示的正确字段定义并插入与db.spr_details.SPR_name 字段中存在的值匹配的字符串值,则不应出现任何错误。

    还请注意,web2py 假设键控表将一起使用(即,被引用表和引用表都将被键控)。因此,例如,如果您将SQLFORMmy_master_table 一起使用,默认情况下它将假定因为my_master_table 没有键控,所以它引用的@​​987654340@ 表也没有。因此它将尝试将SPR_details 的值转换为整数ID(这会导致转换为0,从而导致外键约束错误)。要解决这个问题,您应该手动处理数据库插入和更新——例如:

    form = SQLFORM(db.my_master_table).process(dbio=False)
    if form.accepted:
        db.my_master_table.insert(**form.vars)
    

    在上面,设置dbio=False 可以防止SQLFORM 自己执行插入操作(这将导致错误)。相反,插入是使用form.vars 中的值显式完成的。

    【讨论】:

    • 您好安东尼,感谢您的回复。在发布之前,我尝试了几乎所有的可能性,但没有运气。我什至也尝试过您的解决方案,但即便如此,同样的错误也会出现。看起来就像文档中提到的那样,除了 DB2 和 MySQL 之外,并非所有数据库都支持它。很奇怪,但看起来数据库的这个基本功能目前不存在。所以有了这个,我只能用 id 去。如果您能想到任何解决方法或建议,请告诉我。感谢您在这里帮助我。
    • 在 SQLite 中使用上面的代码绝对有效。如果您仍然遇到错误,我建议您显示用于插入的确切代码。此外,受支持的数据库列表显示 DB2、MS-SQL、Ingres 和 Informix,尽管我认为这不是最新的——键控表可能适用于大多数受支持的 RDBMS。在任何情况下,键控表功能的目的是支持您别无选择的遗留数据库模式——如果您从头开始创建新数据库,最好坚持使用自动递增 ID 主数据库键。
    • 表结构如下-db.define_table('spr_details', Field('SPR_name', 'string', unique=True, notnull=True), Field('Object_location',notnull=True), Field('NSK_System',notnull=True,), primarykey = ['SPR_name'],migrate=True)db.define_table('my_master_table', Field('Test_id',notnull=True), Field('Test_suite',notnull=True), Field('Test_category',notnull=True), Field('Test_unit',notnull=True), Field('Test_case',notnull=True), Field('Applicability', 'reference spr_details.SPR_name'),migrate=True)
    • 然后我在spr_details 表中插入了一行。此行具有 L36^ASM 作为 Spr Name 列的值。现在,当我尝试为my_master_table 添加记录时,L36^ASM 将出现在适用性列下拉列表中。选择此值后,我单击提交。然后FOREIGN KEY constraint failed 来@Anthony
    • 我的意思是您应该更新问题,而不是在 cmets 中添加其他信息。此外,显示所有代码也很重要——假设您使用的是SQLFORM,但您没有在代码中显示它。假设您使用的是SQLFORM,我已经更新了答案。请注意,我仍然建议坚持使用 spr_details 中的默认 ID 字段(您仍然可以另外包含 SPR_name 字段 - 只是不要将其用作主键)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-01
    • 1970-01-01
    • 2021-07-03
    • 2018-06-10
    相关资源
    最近更新 更多