Внешний ключ с различителем

#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 будет установлен виртуальный флаг, и она больше не будет выделять место для хранения строк на диске. Но, возможно, вы правы, переархивирование может быть лучшим выбором. Это неудобная проблема.