使用循环外键删除

时间:2011-11-14 03:05:53

标签: doctrine-orm

我有两个实体,每个实体互相引用:Page实体引用defaultUrlUrl实体引用page

这是周期性的,所以一旦我添加了一个页面和一个url相互引用的内容,我就无法删除它们。

我可以看到两种方法来解决它,但我不确定采用“学说”方式。

  1. 使其中一个关系仅为索引,但不是外键约束
  2. 删除时,请关闭外键约束检查
  3. 我无法弄清楚如何做这些......你知道吗?

    谢谢!

2 个答案:

答案 0 :(得分:2)

这是Doctrine设置它的方法。如前所述,您需要将至少一个外键设置为可为空。

还要考虑将onDelete级联设置为SET NULL。这将使删除过程更简单 - 在删除记录之前,您不必将密钥更新为NULL。

您的schema.yml可能如下所示:

Url:
  columns:
    page_id: { type: integer, notnull: true }
  relations:
    Page: { local: page_id, foreign: id }

Page:
  columns:
    default_url_id: { type: integer, notnull: false }  # ALLOWS NULL foreign key here
  relations:
    DefaultUrl: { class: Url, local: default_url_id, foreign: id, onDelete: SET NULL }

答案 1 :(得分:1)

经验法则,在制作外键时,总是使一个可以为空或省略一个外键定义。

这允许循环中断。

最简单的情况(SQL语法,但是适用了sampe原则):

CREATE TABLE Employee (
    EmployeeId INTEGER NOT NULL IDENTITY(1,1)
    ManagerId INTEGER NOT NULL
    --...
    PRIMARY KEY EmployeeId NONCLUSTERED
    FOREIGN KEY FK_Manager REFRENCES Employee(EmployeeId)
)

可以按如下方式循环断开:

CREATE TABLE Employee (
    EmployeeId INTEGER NOT NULL IDENTITY(1,1)
    ManagerId INTEGER NOT NULL
    --...
    PRIMARY KEY EmployeeId NONCLUSTERED
)

或如下:

CREATE TABLE Employee (
    EmployeeId INTEGER NOT NULL IDENTITY(1,1)
    ManagerId INTEGER NULL
    --...
    PRIMARY KEY EmployeeId NONCLUSTERED
    FOREIGN KEY FK_Manager REFRENCES Employee(EmployeeId)
)

我更喜欢在声明外键时始终跟踪图表并确保没有周期。在所有循环都被打破之前,我将省略最不危险的密钥。这样可以确保可以批量导出所有表,然后将批量导入到另一个数据库中。

编辑:我发现当你向书籍专家询问这个问题时,你会得到一个答案,例如在删除期间关闭外键。出于两个原因,这是错误的。首先,正常的事务操作不应该改变模式定义。其次,代码的其余部分需要外键,因此不会在应用程序代码中处理它;但是,模式修改有一个讨厌的习惯,即在事务中流血或锁定整个表。