tl;dr как лучше делать подчинение одной таблицы многим таблицам (но для одной записи — один владелец). Много опциональных FK или один INTEGER с ручной проверкой?
Вот к примеру, есть у меня таблицы с разными «сущностями», и надо ко всем дать возможность «прикреплять документы». Делаю так:
CREATE TABLE objects (object INTEGER PRIMARY KEY);
CREATE TABLE tasks (task INTEGER PRIMARY KEY);
CREATE TABLE records (record INTEGER PRIMARY KEY);
CREATE TABLE documents (
    object          INTEGER, -- возможный владелец
    task            INTEGER, -- возможный владелец
    record          INTEGER, -- возможный владелец, но...
    side            INTEGER NOT NULL DEFAULT 0, -- ... у него несколько "сторон"
    -- тут собственно описание документа
    name            TEXT NOT NULL, -- неуникальное
    originalName    TEXT NOT NULL, -- неуникальное
    relativePath    TEXT NOT NULL, -- неуникальное
    position        INTEGER NOT NULL, -- (!) уникальное, для сортировки
    -- гарантируем уникальность по владельцу и позиции
    UNIQUE (object, task, record, side, position),
    FOREIGN KEY (object)
        REFERENCES objects (object)
        ON DELETE CASCADE
        ON UPDATE CASCADE,
    FOREIGN KEY (task)
        REFERENCES tasks (task)
        ON DELETE CASCADE
        ON UPDATE CASCADE,
    FOREIGN KEY (record)
        REFERENCES records (record)
        ON DELETE CASCADE
        ON UPDATE CASCADE
);
Сразу скажу, что все это работает через прослойку, т.е. работа с данными происходит без знания о том, что все это бачится на SQL-е. Сделано для того, чтобы можно было прозрачно менять бакенд. Кстати у базы только один эксклюзивный коннект.
У всех трех владельцев сквозная нумерация, так что PRIMARY KEY уникален внутри всех трех таблиц. Выборка документов планируется только внутри владельца, то есть выяснять к какой таблице относится ключ владельца — ненужно. Т.о. можно было бы сделать только одно поле владельца «owner INTEGER NOT NULL» без FOREIGN KEY (оставив костыль side для record) и самому реализовать каскады. Какой подход более правильный?
Теперь второй вопрос, чем-то схожий. У objects есть значения атрибутов в отдельной таблице (схема типизации в таблицах objectTypes и objectAttributes, здесь не привожу):
CREATE TABLE objectValues (
    object          INTEGER NOT NULL, -- FK
    attribute       INTEGER NOT NULL, -- FK
    objectValue     INTEGER, -- или это
    scalarValue     BLOB, -- или это
    PRIMARY KEY (object, attribute),
    FOREIGN KEY (object)
        REFERENCES objects (object)
        ON DELETE CASCADE
        ON UPDATE CASCADE,
    FOREIGN KEY (attribute)
        REFERENCES objectAttributes (attribute)
        ON DELETE CASCADE
        ON UPDATE CASCADE,
    FOREIGN KEY (objectValue)
        REFERENCES objects (object)
        ON DELETE RESTRICT
        ON UPDATE CASCADE
);
И побочный вопрос: если запись однозначно идентифицируется по полю TEXT, нужно ли создавать синтетический первичный ключ, или можно спокойно использовать TEXT как FK?

