1

Одна из моих таблиц order имеет отношение one to many к двум другим таблицам PaymentMethod1 и PaymentMethod2. Я создал отдельные таблицы «способ оплаты», так как они имеют совершенно разные атрибуты, поэтому я могу избежать нулей. Но конкретный ряд в order будет ссылаться на конкретный ряд любой таблицы - PaymentMethod1 ИЛИ PaymentMethod2. Это требует, чтобы значения первичного ключа были уникальными в обеих этих таблицах, то есть ни одна из двух строк в PaymentMethod1 и PaymentMethod2 не может иметь один и тот же первичный ключ.Нет двух строк разных таблиц, имеющих один и тот же первичный ключ?

enter image description here

Am I прямо в первичных ключей они выбрали для PaymentMethod1 и PaymentMethod2 таким образом? Если да, то как его реализовать?

ответ

2

У MySQL нет встроенного метода обработки этого типа полиморфизма.

Одним из решений является наличие двух столбцов внешнего ключа в таблице order, один для первого способа оплаты и один для второго метода оплаты. Разрешить NULL и только заполнить соответствующий.

Этот метод позволяет вам продолжать использовать ограничения внешнего ключа, но он не полностью нормализован.

Другой метод - взять ключ метода оплаты из таблицы order и вместо этого иметь две таблицы переходов, по одному для каждого типа оплаты. Используйте эти таблицы соединений, чтобы присоединиться к таблице order к соответствующему типу платежа. Этот метод также позволяет использовать ограничения внешнего ключа и более нормализуется, чем предыдущий метод (значения NULL не нужны), но отношения внешнего ключа (и запросы) немного сложнее.

+0

здесь таблица 'order' будет иметь соотношение 1: 1 с каждой из таблиц соединения, правильно? –

+0

Для второго решения таблица заказов будет иметь отношение 1: 0..1 к каждой таблице соединений. –

+0

прав, вот что я имел в виду. Я приму свой ответ. :) –

3

Это ограничивающий способ решения проблемы. Что произойдет, если вы добавите новый тип оплаты? Новая таблица поднимается, и ваше условие JOIN для всех ваших запросов, использующих заказы и типы платежей, должно быть переписано.

Если вы в будущем можете ввести больше типов платежей, подумайте о наличии единой таблицы типов платежей, в которой будут храниться тип и атрибуты платежа, которые ВСЕГДА бывают общими для всех типов платежей, а затем отдельную таблицу атрибутов, которая будет удерживаться атрибуты в строках на основе типов платежей. Таким образом, когда вы масштабируете масштаб, вы увеличиваете количество записей, а не количество объектов (таблицы и поля).

Если вы остаетесь с тем, что у вас есть, вам нужно будет либо написать номер заказа в свою таблицу «Типы платежей», чтобы вы могли присоединиться к ним, либо вам нужно будет написать Тип типа оплаты, а также Первичный ключ «Тип платежа» в таблицу заказа. Что-то вроде:

Order Number | Payment Type Type | Payment Type Key 
    1    PaymentType1   5 
    2    PaymentType2   5 
    3    PaymentType1   5 

Тогда:

SELECT 
    o.Number, 
    COALESCE(pm1.key, pm2.key), 
    CASE WHEN o.PaymentTypeType = "PaymentType1" 
     THEN pm1.pm1_attr1 
     ELSE pm2.pm2.attr3 
     END as "Friendly Attribute Name" 
FROM ORDER o 
    LEFT OUTER JOIN PaymentMethod1 pm1 ON 
     o.PaymentTypeType = "PaymentType1" AND 
     o.PaymentTypeKey = pm1.key 
    LEFT OUTER JOIN PaymentMethod2 pm2 ON 
     o.PaymentTypeType = "PaymentType2" AND 
     o.PaymentTypeKey = pm2.key 

Вы можете увидеть, что может получить уродливые довольно быстро. Особенно, когда вы добавляете новый PaymentType в микс через год.

+0

Я бы избегал модели [EAV] (http://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model) для «таблицы атрибутов». Вы когда-нибудь пытались опросить EAV? Это быстро становится неприятным. Если вы собираетесь иметь общие столбцы в одной таблице и отходить в другую таблицу (опять же, не EAV), то вы все еще разветвляетесь на несколько таблиц и снова теряете свои внешние ограничения. Дизайн, который вы предлагаете, является распространенной ошибкой. –

+0

@JNevill, извините за поздний ответ. Имел экзамены.Не могли бы вы рассказать о таблице «Атрибуты», которую вы упомянули в своем предложении? Как я могу создать ** одну таблицу 'Атрибуты', в которой будут храниться все дополнительные атрибуты разных типов платежей? Разве вы не думаете, что в нем будет значительная сумма значений «null» (поскольку таблица состоит из всех возможных дополнительных атрибутов, некоторые из них могут быть «null» для определенного типа оплаты). Кроме того, мне может потребоваться добавить дополнительный атрибут в таблицу «Атрибуты», если я разрешу новый способ оплаты в будущем. –

Смежные вопросы