SQL / ORACLE- FOREIGN KEY с использованием двух столбцов из других таблиц - PullRequest
1 голос
/ 27 сентября 2019

Я пытаюсь создать таблицу в SQL * Plus, которая обращается к двум столбцам из другой таблицы.Например,

Если таблица A выглядит примерно так:

CREATE TABLE Customers
(Customer_ID int NOT NULL PRIMARY KEY, 
NAME Varchar(30) NOT NULL,
PHONE Varchar(12) NOT NULL,
OUTSTANDING_FEES Varchar(10) NULL);

И если моя таблица B выглядит примерно так:

CREATE TABLE Customer_Fees
(Fee_ID int NOT NULL PRIMARY KEY,
FEE_TYPE Varchar(20) NOT NULL,
AMOUNT Varchar(10) NOT NULL,
CUSTOMER_ID int NOT NULL);

Я хочу заполнитьOUTSTANDING_FEES в таблице A с AMOUNT в таблице B, где CUSTOMER_ID совпадает среди таблиц.В моих целях я могу предположить, что любой идентификатор Customer_ID в таблице B появится в таблице только один раз.

Я попытался создать обе таблицы, при этом поле таблицы OUTSTANDING_FEES было пустым, а затем присвоило ему значение FOREIGN KEY, которое ссылается на поле AMOUNT таблицы B, но оно не работает, так как мне нужно убедиться, что оно также содержит перекрестные ссылкиполя CUSTOMER_ID в обеих таблицах.

Спасибо, если поможете!

Ответы [ 2 ]

0 голосов
/ 29 сентября 2019

В модели данных, поставленной в вопросе, есть несколько ошибок.

  1. Определение OUTSTANDING_FEES и AMOUNT в качестве столбцов varchar2 является неправильным моделированием данных, поскольку оба они, несомненно, предназначены для числовых (денежных) значений.Хорошей практикой всегда является использование наиболее подходящего типа данных для атрибута, который мы моделируем.

  2. Создание внешнего ключа между OUTSTANDING_FEES и AMOUNT неверно, поскольку они не являются уникальными идентификаторами.Сумма денег, причитающаяся одному клиенту, может быть такой же, как сумма денег, причитающаяся любым другим, даже всем клиентам (в начале семестра все студенты должны платить одинаковую сумму за обучение).Итак, иностранец, который "ссылается на поля CUSTOMER_ID в обеих таблицах" - это все, что нужно.

  3. Модель данных не предоставляет какого-либо атрибута, который позволяет намчтобы различать уплаченные сборы и сборы, которые не выплачены.

  4. Спрашивающий утверждает, что "Я могу предположить, что любой идентификатор Customer_ID в таблице B появится только один раз втаблица ", но в реальной жизни мы ожидаем, что клиенты будут иметь несколько учетных записей, неоплаченных и оплаченных.Почему бы не смоделировать это?В противном случае, если между Клиентом и Комиссией действительно есть соотношение 1: 1, то нет необходимости в двух таблицах.

Итак, вот улучшенная модель.Он использует надлежащий тип данных для денежных значений;он применяет внешний ключ между двумя таблицами, используя CUSTOMER_ID;следовательно, он поддерживает отношения «один ко многим» между Клиентом и Комиссией;наконец, он отслеживает уплаченные и неоплаченные сборы.

create table customers
( customer_id integer      not null constraint cust_pk primary key
, name        varchar2(30) not null
, phone       varchar2(12) not null
)
/

create table customer_fees
( fee_id       integer      not null constraint fees_pk primary key
, fee_type     varchar2(20) not null
, amount       number       not null
, invoice_date date         not null
, paid_date    date             null
, customer_id  integer      not null constraint fees_cust_fk references customers 
)
/

А, а как насчет OUTSTANDING_FEES?Ну, эта информация выводится из данных в двух таблицах.Есть много способов написания этого запроса, этот подход является просто выбором:

select cust.customer_id
       , cust.name
       , cust.phone
       , fees.outstanding_fees
from   customers cust
       left outer join 
        ( select fees.customer_id
               , sum(case when fees.paid_date is null then fees.amount 
                     else 0 end) as outstanding_fees
          from customer_fees fees
          group by fees.customer_id ) fees on fees.customer_id = cust.customer_id

/ 

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

0 голосов
/ 27 сентября 2019

Нельзя создать внешний ключ для неосновного столбца из другой таблицы.Вам придется создать FK для FEE_ID.

CREATE TABLE Customers (
Customer_ID int NOT NULL PRIMARY KEY, 
NAME Varchar(30) NOT NULL,
PHONE Varchar(12) NOT NULL,
OUTSTANDING_FEES Varchar(10) FOREIGN KEY REFERENCES Customer_Fees(FEE_ID)
);

Вы можете использовать поле AMOUNT в предложении select.

Select A.Customer_ID,B.AMOUNT from Customers A Join Customer_Fees B
on A.OUTSTANDING_FEES = B.FEE_ID
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...