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