Strange foreign key behavior on empty tables in SQ

2020-04-30 10:40发布

I have SQLite 3 with the following setup (simplified):

create table Location(LocationId integer not null,
                      LocationCode text not null, 
                      primary key(LocationId),
                      unique(LocationCode));

The table above is being referenced by Department:

create table Department(DepartmentId integer not null,
                        LocationId integer not null,
                        DepartmentCode text not null,
                        primary key(LocationId, DepartmentCode),
                        foreign key(LocationId) references Location(LocationId));

The table above is being referenced by Child:

create table Event(EventId integer not null,
                   LocationId integer not null,
                   unique(LocationId, EventDate),
                   primary key(eventId),
                   foreign key(LocationId) references Location(LocationId));

The table above references table Location:

create table Parent(ParentId integer not null,
                    EmailAddress text not null,
                    primary key(ParentId),
                    unique(EmailAddress));

The table above is being referenced by table Child:

create table Child(ChildId integer not null,
                   ParentId integer not null,
                   ChildCode text not null,
                   DepartmentId integer not null,
                   primary key(ChildId, ParentId),
                   foreign key(ParentId) references Parent(ParentId),
                   foreign key(DepartmentId) references Department(DepartmentId));

The table child is the one I'm trying to delete from.

At this point, the whole database is empty, and has "pragma foreign_keys=ON".

While testing a script to clear the database I encountered an error while deleting from the empty table Child having a foreign key to the (also empty) table Parent.

When I issue the command delete from child (while is already empty), SQLite3 comes back with the error message "foreign keys mismatch".

This is the vital part of the delete script:

delete from Child;
delete from Parent;
delete from Event;
delete from Department;
delete from Location;

I saw some posts here about temporarily disabling foreign key support, but that does not make sense to me. That makes the whole process of implementing a foreign key relationship unnecessary.

1条回答
男人必须洒脱
2楼-- · 2020-04-30 11:24

The documentation (hidden in the source code) says:

A foreign key constraint requires that the key columns in the parent table are collectively subject to a UNIQUE or PRIMARY KEY constraint. […] If the required index cannot be found, either because:

  1. The named parent key columns do not exist, or
  2. The named parent key columns do exist, but are not subject to a UNIQUE or PRIMARY KEY constraint, or
  3. No parent key columns were provided explicitly as part of the foreign key definition, and the parent table does not have a PRIMARY KEY, or
  4. No parent key columns were provided explicitly as part of the foreign key definition, and the PRIMARY KEY of the parent table consists of a a different number of columns to the child key in the child table.

then … a "foreign key mismatch" error [is raised].

> DELETE FROM Child;
Error: foreign key mismatch
> CREATE UNIQUE INDEX di ON Department(DepartmentId);
> DELETE FROM Child;
> 
查看更多
登录 后发表回答