#sql #database #oracle
#sql #База данных #Oracle
Вопрос:
У меня есть одна таблица STATUSES, содержащая статусы для большего количества таблиц:
TABLE_NAME | STATUS_ID | STATUS_NAME
=========== =========== ============
TAB_1 | 1 | New
TAB_1 | 2 | Started
TAB_1 | 3 | Complete
TAB_2 | 1 | Empty
TAB_2 | 2 | Full
Таблица СТАТУСОВ содержит первичный ключ двух столбцов (имя_таблицы,status_id).
Тогда у меня есть таблица TAB_1:
ID | STATUS_ID | TAB_VALUE
=== =========== ==========
1 | 1 | Value1
Когда я хочу получить значения таблицы со статусом, я использую следующий SQL-запрос:
SELECT id,tab_value,status_name
FROM tab_1 t
JOIN statuses s ON (s.status_id=t.status_id AND s.table_name='TAB_1')
Теперь я хотел бы создать внешний ключ из TAB_1 в STATUSES, но STATUS_ID должен отличаться именем таблицы!
Я пробовал что-то вроде этого:
ALTER TABLE tab_1
ADD CONSTRAINT tab_1_status_fk FOREIGN KEY ('TAB_1',status_id)
REFERENCES statuses (table_name,status_id)
ENABLE;
Конечно, это не работает (иначе меня бы здесь не было).
Возможно ли создать такой внешний ключ с помощью ‘distinguisher’?
Ответ №1:
Я думаю, я бы добавил имя таблицы в виде виртуального столбца с постоянным значением, например
alter table tab_1 add (table_name as ('TAB_1'));
А затем создайте fk, используя это
ALTER TABLE tab_1
ADD CONSTRAINT tab_1_status_fk FOREIGN KEY (table_name,status_id)
REFERENCES statuses (table_name,status_id)
ENABLE;
Редактировать: Если вы используете 12c или выше, вы можете сделать виртуальный столбец скрытым; Я думаю, это все равно будет работать с FK…
alter table tab_1 add (table_name invisible as ('TAB_1'));
Комментарии:
1. Хм, мне не нравится это решение. Эти дополнительные столбцы являются не виртуальными, а реальными, содержащими реальные (те же самые) данные и занимающими пространство (видимое или невидимое). Эти таблицы огромны, тогда лучшим решением было бы разделить объединенную таблицу статусов на отдельную таблицу статусов для каждой таблицы и создать простое отношение FK к ним.
2. Если вы используете
as (EXPRESSION)
предложение при создании столбца, он будет создан как виртуальный столбец, даже если вы не используетеvirtual
ключевое слово. Попробуйте это на тестовой таблице — в таблице DDL будет установлен виртуальный флаг, и она больше не будет выделять место для хранения строк на диске. Но, возможно, вы правы, переархивирование может быть лучшим выбором. Это неудобная проблема.