Гость
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Нужна помощь с написанием триггера / 25 сообщений из 35, страница 1 из 2
08.10.2021, 11:15
    #40102988
Док
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Есть домен
Код: sql
1.
2.
3.
4.
5.
CREATE DOMAIN DMN_BOOL_2 AS
SMALLINT
DEFAULT 0
NOT NULL
CHECK (VALUE IN (0,1));


и табля
Код: sql
1.
2.
3.
4.
5.
6.
CREATE TABLE TBL_PHONE (
    ID                    INTEGER NOT NULL,
    FK_PEOPLE             INTEGER NOT NULL,
    MAIN_CONTACT          DMN_BOOL_2 DEFAULT 1
-- <skiped>
);



Нужно реализовать на триггере: для всех ID у одного FK_PEOPLE сделать MAIN_CONTACT = 0, если у одному из них делается MAIN_CONTACT = 1

1. где реализовать, в Before Insert/Update?
2. как?

был бы благодарен за пример или пинок в нужном направлении
=================
Док.

Win10 Ultim x64/Deb 10 amd64/Darwin Cocoa:
FB 3.0.7.33374, Lazarus 2.3.0(trunk); FPC 3.3.1(trunk)
...
Рейтинг: 0 / 0
08.10.2021, 11:24
    #40102990
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Док,

1. Лучше в after
2. что-то вроде того

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
....
begin
  IF (:NEW.MAIN_CONTACT = 1 AND :NEW.MAIN_CONTACT  <> :OLD.MAIN_CONTACT ) THEN -- второе условие только для update
  BEGIN
     UPDATE TBL_PHONE
     SET MAIN_CONTACT = 0
     WHERE FK_PEOPLE = :NEW.FK_PEOPLE  
        AND MAIN_CONTACT = 1
        AND ID <> :NEW.ID; -- это условие только update триггере
  END
end



З.Ы. я не люблю такие триггеры
...
Рейтинг: 0 / 0
08.10.2021, 11:35
    #40102997
KreatorXXI
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Док,

чего сложного? В After Update типа такого:
Код: sql
1.
2.
3.
4.
if new.main_contact=1 then
  update tbl_phone a
  set a.main_contact=0
  where a.fk_people=new.fk_people and a.id<>new.id


Подводных камней не вижу.
...
Рейтинг: 0 / 0
08.10.2021, 12:01
    #40103007
Док
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Гуд. Спасибо за примеры. Чуть позже опробую и отпишусь
...
Рейтинг: 0 / 0
08.10.2021, 12:29
    #40103013
rdb_dev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Док, я бы сделал иначе - создал ещё одну таблицу MAIN_PHONE с полями PEOPLE_ID (PK и FK к PEOPLES) и PHONE_ID (FK к TBL_PHONE). Потом создал бы VIEW на TBL_PHONE с LEFT JOIN к MAIN_PHONE по PEOPLE_ID и с вычисляемым полем BOOL на MAIN_PHONE.PHONE_ID IS NOT NULL. Не пришлось бы возиться с триггером.
...
Рейтинг: 0 / 0
08.10.2021, 19:44
    #40103169
Док
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
rdb_dev,

ага, вместо одного триггера две таблицы? Оккама плачет :)
...
Рейтинг: 0 / 0
08.10.2021, 20:13
    #40103172
Док
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Вобщем, сделал так:
Код: sql
1.
2.
3.
4.
5.
6.
IF (NEW.MAIN_CONTACT = 1) THEN
  BEGIN
  UPDATE TBL_PHONE PH
     SET PH.MAIN_CONTACT = 0
   WHERE (PH.FK_PEOPLE = NEW.FK_PEOPLE) AND (PH.ID <> NEW.ID);
  END



Причем, работает как в before , так и в after insert/update

Еще раз спасибо за помощь
...
Рейтинг: 0 / 0
08.10.2021, 20:34
    #40103179
ъъъъъ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Док,

если у тебя есть поле FK_PEOPLE - значит, у тебя есть табличка PEOPLE.
Во в ней и размести ссылку на майн контакт.
И триггеров не понадобится. И выборку делать проще будет.
...
Рейтинг: 0 / 0
08.10.2021, 22:17
    #40103190
kdv
kdv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
ДокПричем, работает как в before, так и в after insert/update
ну, делать триггер before, в котором update, это как-то нелогично. А в after самое то.
...
Рейтинг: 0 / 0
08.10.2021, 22:37
    #40103197
hvlad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Док
Вобщем, сделал так:
А теперь посмотри внимательно и сам скажи - почему ты выбрал вариант, который гораздо хуже этого 22381114
...
Рейтинг: 0 / 0
08.10.2021, 22:51
    #40103199
Док
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
hvlad,
С виду опасностей не вижу...

ъъъъъ
Во в ней и размести ссылку на майн контакт.

КМК, не подойдет. В моем понимании, реализовывать консистентность логики и данных надо на уровне сервера, а не клиента.

Если я правильно тебя понял, я должен закольцевать таблички. Тогда при изменении MAIN_CONTACT я еще должен буду в TBL_PEOPLE менять ФК на TBL_PHONE.ID той записи, которая теперь является основным контактом. А это еще триггер. Circulus viciosus получается.
...
Рейтинг: 0 / 0
08.10.2021, 23:05
    #40103203
ъъъъъ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Док
hvlad,
С виду опасностей не вижу...

ъъъъъ
Во в ней и размести ссылку на майн контакт.

КМК, не подойдет. В моем понимании, реализовывать консистентность логики и данных надо на уровне сервера, а не клиента.

Если я правильно тебя понял, я должен закольцевать таблички. Тогда при изменении MAIN_CONTACT я еще должен буду в TBL_PEOPLE менять ФК на TBL_PHONE.ID той записи, которая теперь является основным контактом. А это еще триггер. Circulus viciosus получается.


Как раз наоборот, логика из императивной становится декларативной, в итоге отпадает необходимость в триггерах вообще.
Поле MAIN_CONTACT таблички TBL_PHONE становится ненужным. Для назначения "главной записи" меняется значение ссылки в табличке PEOPLE, вот и всё.
...
Рейтинг: 0 / 0
08.10.2021, 23:19
    #40103207
Док
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
ъъъъъ,

изящно. Только мне на клиенте нужно отображать ВСЕ имеющиеся на данный момент у человека телефоны, из которых один является основным :)
...
Рейтинг: 0 / 0
09.10.2021, 00:44
    #40103213
ъъъъъ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Док
Только мне на клиенте нужно отображать ВСЕ имеющиеся на данный момент у человека телефоны, из которых один является основным :)

Ну вот, смотри.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
CREATE TABLE PEOPLE (
    ID             INTEGER NOT NULL,
    FIO            VARCHAR(255),
    MAIN_PHONE_ID  INTEGER /* Вот он*/
);


CREATE TABLE PHONE (
    ID         INTEGER NOT NULL,
    PEOPLE_ID  INTEGER,
    NMBR       VARCHAR(40) /* Значение номера */
);
...
Рейтинг: 0 / 0
09.10.2021, 00:46
    #40103214
ъъъъъ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Добавляем данные:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
INSERT INTO PEOPLE (ID, FIO, MAIN_PHONE_ID) VALUES (1, 'Иванов Иван Иванович', 1);
INSERT INTO PEOPLE (ID, FIO, MAIN_PHONE_ID) VALUES (2, 'Петров Петр Петрович', 3);
INSERT INTO PEOPLE (ID, FIO, MAIN_PHONE_ID) VALUES (3, 'Васильев Василий Васильевич', NULL);

INSERT INTO PHONE (ID, PEOPLE_ID, NMBR) VALUES (1, 1, '222-22-2222-22');
INSERT INTO PHONE (ID, PEOPLE_ID, NMBR) VALUES (2, 1, '333-33-3333-33');
INSERT INTO PHONE (ID, PEOPLE_ID, NMBR) VALUES (3, 2, '444-44-4444-44');
INSERT INTO PHONE (ID, PEOPLE_ID, NMBR) VALUES (4, 2, '555-55-5555-55');
INSERT INTO PHONE (ID, PEOPLE_ID, NMBR) VALUES (5, 3, '666-66-6666-66');
INSERT INTO PHONE (ID, PEOPLE_ID, NMBR) VALUES (6, 3, '777-77-7777-77');


Т.е., у Иванова главный телефон это 222-22-2222-22, у Петрова - 444-44-4444-44, а у Васильева - нет.
...
Рейтинг: 0 / 0
09.10.2021, 00:47
    #40103215
ъъъъъ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Добавим констреинтов:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
ALTER TABLE PHONE ADD CONSTRAINT UNQ_PHONE_PEOPLE UNIQUE (PEOPLE_ID, ID);


ALTER TABLE PEOPLE ADD CONSTRAINT PK_PEOPLE PRIMARY KEY (ID);
ALTER TABLE PHONE ADD CONSTRAINT PK_PHONE PRIMARY KEY (ID);


ALTER TABLE PEOPLE ADD CONSTRAINT FK_PEOPLE_MAIN_PHONE FOREIGN KEY (ID, MAIN_PHONE_ID) REFERENCES PHONE (PEOPLE_ID, ID);
ALT



Составной ключ в констреинте для того, чтобы пиплу не назначили главным чужой номер. Если бизнеслогика этого не требует - составной ключ не нужен.
...
Рейтинг: 0 / 0
09.10.2021, 00:49
    #40103216
ъъъъъ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Список всех пиплов, с их основными номерами:

Код: sql
1.
2.
3.
select P.ID, P.FIO, PH.NMBR as MAIN_PHONE
from PEOPLE P
left join PHONE PH on PH.ID = P.MAIN_PHONE_ID   
...
Рейтинг: 0 / 0
09.10.2021, 00:56
    #40103217
ъъъъъ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Док,

И, наконец,
Док
мне на клиенте нужно отображать ВСЕ имеющиеся на данный момент у человека телефоны, из которых один является основным :)

-
Код: sql
1.
2.
3.
4.
select PH.ID, PH.NMBR, iif(P.ID is not null, 'Main', null) IS_MAIN_PHONE
from PHONE PH
left join PEOPLE P on P.MAIN_PHONE_ID = PH.ID
where PH.PEOPLE_ID = :PEOPLE_ID   



Например, для :PEOPLE_ID равным 1, результат:
...
Рейтинг: 0 / 0
09.10.2021, 11:38
    #40103256
hvlad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Док
С виду опасностей не вижу...
Твой триггер апдейтит все записи (кроме текущей) с таким же FK_PEOPLE - а достаточно только одной.
Причём делает он это после любого апдейта "главной" записи, даже если MAIN_CONTACT не менялось.

PS способ 22381418 гораздо лучше
...
Рейтинг: 0 / 0
09.10.2021, 12:01
    #40103259
Док
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
ъъъъъ,

Понял. Тоже вариант, конечно. Спасибо.

hvlad
Твой триггер апдейтит все записи (кроме текущей) с таким же FK_PEOPLE - а достаточно только одной.

Ага, вот ты о чем. Согласен, конечно, апдейтить ВСЕ записи телефонов одного ФК - не комильфо. С другой стороны, ну сколько телефонов м.б. у пациента в базе? Сервер и не заметит :)

Способ Дениса универсальнее и правильнее (возьму на заметку "в целях повышения общей образованности" ©), а способ KreatorXXI - в моем случае практичнее, КМК.
...
Рейтинг: 0 / 0
09.10.2021, 14:19
    #40103279
hvlad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Док,

кто я такой, чтобы учить доктора соблюдать гигиену и не применять кривые методы лечения ?
...
Рейтинг: 0 / 0
09.10.2021, 17:01
    #40103311
Док
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
hvlad,

Влад, я не спорю. Просто до меня иногда долго доходит :)

А так кошерно будет?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
CREATE OR ALTER TRIGGER TBL_PHONE_AIU0 FOR TBL_PHONE
ACTIVE AFTER INSERT OR UPDATE POSITION 0
AS
BEGIN
IF (NEW.MAIN_CONTACT = 1) THEN
  BEGIN
  UPDATE TBL_PHONE PH
     SET PH.MAIN_CONTACT = 0
   WHERE (PH.FK_PEOPLE = NEW.FK_PEOPLE) AND (PH.ID <> NEW.ID) AND (PH.MAIN_CONTACT = 1);
  END
END


Вроде работает (и на вставку и на апдейт) и обновляет только те записи, которые надо изменить
...
Рейтинг: 0 / 0
10.10.2021, 00:07
    #40103376
ъъъъъ
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Вот лентяй...
...
Рейтинг: 0 / 0
10.10.2021, 00:24
    #40103378
hvlad
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Док
А так кошерно будет?
Ты учёл ровно половину рекомендаций.
Учтёшь вторую - получится триггер как у Дениса.
И нужно ещё что-то делать с удалениями, или не нужно - тут тебе виднее.
...
Рейтинг: 0 / 0
11.10.2021, 09:03
    #40103475
rdb_dev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Нужна помощь с написанием триггера
Док
rdb_dev,
ага, вместо одного триггера две таблицы? Оккама плачет :)
Док, почему нет? Во-первых, в данном случае, две таблицы, это лучший вариант нормализации, а во-вторых, триггер создаёт больше хлопот, так как, при изменении основного контакта, для обеспечения целостности тебе надо блокировать на изменение все записи контактов врача до подтверждения транзакции лишь ради изменения флага. Впрочем, хозяин - барин...
...
Рейтинг: 0 / 0
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Нужна помощь с написанием триггера / 25 сообщений из 35, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]