Given the following tables:
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);
When a department is deleted, I want the following statements to execute atomically:
- The departmentsrow is deleted
- The permissionsrow associated with the department row is deleted
- The companiesrow associated with the department row is deleted
- The permissionsrow associated with the company (previous point) is deleted
Questions:
- If I use READ_COMMITTEDtransaction isolation andON CASCADE DELETEon all foreign keys, are the rows deleted as a single atomic statement? Or are they executed as separate delete statements which are vulnerable toREAD_COMMITTEDanomalies?
- How do I instruct the database to delete the company/department permission when the company/department gets deleted (atomically, if possible)?
- Does the SQL standard say anything about this question? Or does the behavior differ across different databases?
CLARIFICATIONS:
- company/department need to reference the permissions table and not the other way around. This is because permissionsforms a Closure Table (e.g. a user has permission to a company, and a company has permission to a department, therefore a user has permission to the department). Because the hierarchical relationship spans different types (i.e. users, companies, departments) the permissions table cannot point to a specific type. Therefore, company/department must reference a permission and not the other way around.
- Say I want to delete a Department, it isn't sufficient for me to delete its Permission and let CASCADEtake care of the rest because it'll delete the Department's permission, the Department and Company but it'll neglect to delete the company's Permission.
- I cannot use a trigger to delete a permission after a company/department has been deleted because H2 runs triggers in a separate database connection than the main statement and the two request a write lock on the same company/department row. The first connection locks theThis was caused by a limitation of H2 for which there is a workaround. See https://groups.google.com/d/msg/h2-database/B3xG488RBhI/DOsIMVmPBnAJ- companiesrow I am deleting. The second connection (trigger) attempts to delete the- permissionsrow associated with the company but- ON CASCADE DELETErequires it to lock the company as well.
 
     
    