【问题标题】:How to delete a row's foreign key when it is deleted?删除行的外键时如何删除?
【发布时间】:2013-05-28 04:12:06
【问题描述】:

给定以下表格:

create table permissions(id identity);
create table companies(id identity, 
    permission_id bigint not null, 
    foreign key(permission_id) references permissions(id) on delete cascade);
create table departments(id identity, 
    company_id bigint not null, 
    permission_id bigint not null, 
    foreign key(company_id) references companies(id), 
    foreign key(permission_id) references permissions(id) on delete cascade);

当一个部门被删除时,我希望以下语句原子执行:

  • departments 行已删除
  • 与部门行关联的permissions 行被删除
  • 与部门行关联的companies 行被删除
  • 与公司(前一点)关联的permissions 行已删除

问题:

  1. 如果我在所有外键上使用READ_COMMITTED 事务隔离和ON CASCADE DELETE,这些行是否会作为单个原子语句被删除?还是它们是作为容易受到READ_COMMITTED 异常影响的单独删除语句执行的?
  2. 当公司/部门被删除时,我如何指示数据库删除公司/部门权限(如果可能,以原子方式)?
  3. SQL 标准对这个问题有任何说明吗?或者不同数据库的行为是否不同?

澄清:

  1. 公司/部门需要引用权限表,而不是相反。这是因为permissions形成了Closure Table(例如,用户对公司有权限,公司对部门有权限,因此用户对部门有权限)。由于层次关系跨越不同类型(即用户、公司、部门),权限表不能指向特定类型。因此,公司/部门必须引用许可,而不是相反。
  2. 假设我要删除一个部门,我删除它的权限是不够的,让CASCADE处理剩下的,因为它会删除部门的权限,部门和公司,但它会忽略删除公司的许可。
  3. 在删除公司/部门后,我无法使用触发器来删除权限,因为 H2 在与主语句不同的数据库连接中运行触发器,并且两者请求对同一公司/部门行进行写锁定。第一个连接锁定了我要删除的companies 行。第二个连接(触发器)尝试删除与公司关联的permissions 行,但ON CASCADE DELETE 要求它也锁定公司。 这是由 H2 的限制引起的,有一个解决方法。见https://groups.google.com/d/msg/h2-database/B3xG488RBhI/DOsIMVmPBnAJ

【问题讨论】:

  • 您能否澄清一下“部门已被删除”的含义。您的意思是删除部门表中具有给定部门ID的行吗?如果是这种情况,则“department.permission_id is deleted”语句没有多大意义,因为整行都被删除了。还是您的意思是该行应该保留,并且只有列 permission_id 应该设置为 null?
  • @ThomasMueller,很抱歉造成混淆。请参阅修改后的问题。

标签: sql h2 cascading-deletes


【解决方案1】:

它在大多数数据库中都是原子的,除了带有 MyISAM 和 MS Access 的 mysql,通常你可以用触发器做你想做的事,但这很奇怪,因为通常与我们想要的相反,我的意思是当一个权限是删除,那么拥有该权限的部门也会被删除

【讨论】:

  • 我已经阐明了权限表背后的设计目标。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-09
  • 2012-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-18
  • 2013-03-26
相关资源
最近更新 更多