Похоже, у вас есть это в вашем реляционном взгляде на ситуацию.
Cluster : name, other attributes of cluster
Server : name, optional FK to cluster, other attributes of a server
Database : name, (FK to cluster OR FK to server)
Проблема в том, что у вас есть несколько более сложная ситуация в реальном мире, та, которую реляционные технологии не отражают четко.
Host -- an abstract superclass for places a database can run.
Cluster (extends Host) : name, etc.
Server (extends Host) : name, optional FK to cluster.
Database : FK to Host
У вас есть несколько вариантов решения этой проблемы "субъективности".
Сверните узел, кластер и сервер в одну таблицу. Это приводит к рекурсивным отношениям между хостом (как кластером) и хостом (как сервером). Это немного раздражает, но создает единую таблицу для хоста, кластера и сервера. Результирующая таблица имеет много пустых значений (строки кластера используют одну группу столбцов, строки сервера используют другой набор столбцов.) Вам необходимо добавить столбец, чтобы различать подгруппы узла.
Передать информацию о хосте в кластер и сервер. Это полезно, когда у вас есть много общей информации в таблице хостов и очень мало специфичной для подкласса информации в таблицах кластера или сервера. Таблицы кластеров и серверов выглядят очень похоже (по сути, это клоны хоста) с несколькими разными столбцами.
Использование соединения между (хост и кластер) или (хост и сервер) на основе дискриминатора в хосте. Хотя это довольно сложно, это хорошо масштабируется, потому что все базы данных присоединены к хосту, а полный список хостов представляет собой объединение хостов, которые присоединяются к серверу, и хосты, которые присоединяются к кластеру.
Использовать необязательные поля FK в базе данных. Для этого требуется объединение базы данных, соединенной с кластером, и базы данных, соединенной с сервером, чтобы получить полный список баз данных. Каждая база данных может иметь дискриминатор, чтобы вы могли различать различные комбинации значений NULL в двух полях FK. Существует четыре возможных комбинации, две из которых разумны, а две могут быть запрещены. Попытка просто использовать два обнуляемых FK обычно не работает хорошо, поэтому вам часто требуется флаг состояния, чтобы отделить базу данных на кластере от базы данных на сервере от базы данных, которой ничего не назначено, от базы данных с неизвестным хостингом от любого другого состояния, которое может быть отношение.