【发布时间】: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行已删除
问题:
- 如果我在所有外键上使用
READ_COMMITTED事务隔离和ON CASCADE DELETE,这些行是否会作为单个原子语句被删除?还是它们是作为容易受到READ_COMMITTED异常影响的单独删除语句执行的? - 当公司/部门被删除时,我如何指示数据库删除公司/部门权限(如果可能,以原子方式)?
- SQL 标准对这个问题有任何说明吗?或者不同数据库的行为是否不同?
澄清:
- 公司/部门需要引用权限表,而不是相反。这是因为
permissions形成了Closure Table(例如,用户对公司有权限,公司对部门有权限,因此用户对部门有权限)。由于层次关系跨越不同类型(即用户、公司、部门),权限表不能指向特定类型。因此,公司/部门必须引用许可,而不是相反。 - 假设我要删除一个部门,我删除它的权限是不够的,让
CASCADE处理剩下的,因为它会删除部门的权限,部门和公司,但它会忽略删除公司的许可。 -
在删除公司/部门后,我无法使用触发器来删除权限,因为 H2 在与主语句不同的数据库连接中运行触发器,并且两者请求对同一公司/部门行进行写锁定。第一个连接锁定了我要删除的这是由 H2 的限制引起的,有一个解决方法。见https://groups.google.com/d/msg/h2-database/B3xG488RBhI/DOsIMVmPBnAJcompanies行。第二个连接(触发器)尝试删除与公司关联的permissions行,但ON CASCADE DELETE要求它也锁定公司。
【问题讨论】:
-
您能否澄清一下“部门已被删除”的含义。您的意思是删除部门表中具有给定部门ID的行吗?如果是这种情况,则“department.permission_id is deleted”语句没有多大意义,因为整行都被删除了。还是您的意思是该行应该保留,并且只有列 permission_id 应该设置为 null?
-
@ThomasMueller,很抱歉造成混淆。请参阅修改后的问题。
标签: sql h2 cascading-deletes