Страницы

Поиск по вопросам

воскресенье, 7 июля 2019 г.

Внешний ключ или достаточно триггера?

Возник вопрос касаемо SQL (сразу говорю, что я SQL знаю не совсем хорошо). К примеру, в таблице Касса нужно обновлять данные, которые изменяют в Товарах или Пациентах. Таблица CashBox и Cashless (одинаковые, только в одну наличная, в другую - безналичная оплата)
CREATE TABLE CashBox(ID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, Operation VARCHAR(1000), Income DOUBLE PRECISION, Consumption DOUBLE PRECISION, Balance DOUBLE PRECISION, DateTime TIMESTAMP);
Сделал внутреннюю таблицу для идентификаторов IntCashBox, IntCashless
CREATE TABLE IntCashBox (ID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, SourcePatientID INTEGER NOT NULL, SourceGoodsID INTEGER NOT NULL, CONSTRAINT fk_SourcePatientID(SourcePatientID) references Patients(id), CONSTRAINT fk_SourceGoodID references fk_SourceGoodID(SourceGoodsID));
Таблица (предыдущая версия) до FOREIGN KEY:
CREATE TABLE IntCashBox (ID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, SourceID INTEGER, TableName VARCHAR(50));
Вот я думаю, можно ли использовать WHERE в FOREIGN KEY (чтобы указать, из какой таблицы пришли данные) ? Суть такова: ID могут быть одинаковые в Товарах и Пациентах, а исключить дублирование надо просто сделав пометку, из какой таблицы пришли данные.
Делал триггер (это до FOREIGN KEY), в нем-то можно и без FOREIGN KEY делать все, т.е. триггер для таблиц есть и все работает корректно, т.е. пометка, какая таблица пишется в TableName и в триггере обновление проходит корректно (лишний код убрал):
SELECT SourceID, TableName FROM IntCashBox WHERE SourceID = old.ID into :intSourceID, :sourceTableName; --и определялось, где обновлять UPDATE CashBox SET Income = new.Amount, Balance = new.Amount - Consumption WHERE :intSourceID = old.ID AND :sourceTableName = 'Patients';
И вот так определялось:
if (new.PaymentType = 'Наличная оплата') then BEGIN INSERT INTO IntCashBox ... --и собственно определялась таблица и вставлялось/обновлялось --там были поля SourceID и TableName, по которым и определял END ELSE BEGIN INSERT INTO Cashless END
Можно было бы триггер оставить и не использовать FOREIGN KEY, но я вот думаю, при бэкапе и восстановлении базы идентификаторы сбрасываются или нет(если не просто копировать файл базы, да так и не делают)? К примеру, в крайнем случае, если вдруг придется пересоздавать базу(не значит, что придется, просто рассматриваю самые крайние случаи), чтобы ID были корректны, для этого вроде и нужны внешние ключи?
Суть вопроса - можно решать такие вопросы исключительно триггером, или все равно желательно FOREIGN KEY? Вообще в таких случаях внешний ключ обязателен или нет?


Ответ

Таблица CashBox и Cashless (одинаковые, только в одну наличная, в другую - безналичная оплата)
В этом корень всех проблем. Таблица должна быть одна, а в ней - дополнительное поле IS_CASH, где 1 будет означать "наличные", а 0 - "безналичная оплата". После этого все резко упростится.

Комментариев нет:

Отправить комментарий