Могу ли я создать табличное отношение, только если в таблице root указано значение c? - PullRequest
2 голосов
/ 23 марта 2020

В таблице УСТРОЙСТВО У меня есть ТИП, если ТИП - это ОБОГРЕВАТЕЛЬ, тогда сделайте связь с таблицей ОБОГРЕВАТЕЛЬ, иначе, если ТИП - ЛАМПА, сделайте связь с таблицей ЛАМП. Возможно ли что-то подобное сделать?

Example

@ MikeNakis, поэтому это не должно быть возможным:

Device table:
+-----+----------+----------+
| Id  | LampId   | HeaterId |
+-----+----------+----------+
|   1 | NULL     | 1        |
|   2 | 2        | 2        |
|   3 | 3        | NULL     |
|   4 | NULL     | 4        |
+-----+----------+----------+

Lamp table:
+-----+----
| Id  |
+-----+----
|   2 |
|   3 |
+-----+----

Heater table:
+-----+----
| Id  |
+-----+----
|   1 |
|   2 |
|   4 |
+-----+----

1 Ответ

0 голосов
/ 23 марта 2020

Да, это возможно.

Это один из способов (на мой взгляд, наилучший способ), в которых работают каркасы объектно-реляционного сопоставления (ORM). И это не случайно, потому что вы пытаетесь реализовать здесь объектно-ориентированную иерархию наследования, отображенную в реляционную базу данных. «Устройство» является базовым классом, а «Лампа» и «Нагреватель» являются производными (потомками) классами.

Вот как это сделать:

Избавиться от Type столбец. Как я покажу ниже, он станет вычисляемым столбцом.

Вместо столбца Type введите пару так называемых столбцов "id-потомка": столбец HeaterId и столбец LampId. Добавьте ограничение, если вы sh, что только один из этих столбцов с идентификатором потомка может быть ненулевым. И если вы добавите больше устройств позже, вам придется добавить больше столбцов с идентификатором потомка.

Затем вы можете сделать Type вычисляемым столбцом, на основе которого один из столбцов с идентификатором потомка содержит ненулевое значение.

Плохая новость заключается в том, что вы не сможете установить значение столбца Type, но это нормально; вместо установки Type вы будете неявно определять тип, сохраняя ненулевое значение в одном из столбцов с идентификатором потомка.

Примечание: в объектно-ориентированном программировании очень редко проектируют базовый класс, чтобы иметь какие-либо знания о своих потомках. Некоторые могут даже сказать, что иметь такие знания нелепо. Я не был бы таким абсолютным, я сталкивался с примерами небольших, тесно связанных, нерасширяемых графов классов, где такие знания являются законными и полезными для получения. Но в любом случае, даже если вы строго придерживаетесь принципа, который говорит, что базовый класс никогда не должен ничего знать о своих потомках, это не совсем объектно-ориентированное программирование: это реляционная база данных. И это цена, которую вы должны заплатить, чтобы отобразить граф классов в базу данных.

Дополнительные пояснения:

Во-первых, некоторая терминология: «длинный ряд» - это пара родителей (основание / предок) строка плюс нисходящая строка, исследованная вместе. «Фрагмент строки» - это только один из рассматриваемых отдельно.

Каждый фрагмент строки-потомка должен иметь точно такой же идентификатор первичного ключа, что и его родительский фрагмент строки. Итак, вот пример структуры:

Device table:
+-----+----------+----------+
| Id  | LampId   | HeaterId |
+-----+----------+----------+
|   1 | NULL     | 1        |
|   2 | 2        | NULL     |
|   3 | 3        | NULL     |
|   4 | NULL     | 4        |
+-----+----------+----------+

Lamp table:
+-----+----
| Id  | 
+-----+----
|   2 | 
|   3 | 
+-----+----

Heater table:
+-----+----
| Id  | 
+-----+----
|   1 | 
|   4 | 
+-----+----

Это означает, что во фрагменте базовой строки один идентификатор потомка, который не равен нулю, всегда имеет то же значение, что и первичный ключ этого та же строка.

Этот способ, помимо простоты устранения неполадок, имеет дополнительное преимущество в производительности: вставка всей длинной строки в базу данных не требует каких-либо дополнительных обращений к базе данных: вы используете последовательность или значение автоинкремента для выдачи только одного идентификатора, и это единственный идентификатор, который вам понадобится для всех фрагментов строки, участвующих в вставке. Это работает как очарование, даже если ваша иерархия наследования глубже, чем просто два уровня.

...