powered by simpleCommunicator - 2.0.48     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Нужна помощь с написанием триггера
25 сообщений из 35, страница 1 из 2
Нужна помощь с написанием триггера
    #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
Нужна помощь с написанием триггера
    #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
Нужна помощь с написанием триггера
    #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
Нужна помощь с написанием триггера
    #40103007
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гуд. Спасибо за примеры. Чуть позже опробую и отпишусь
...
Рейтинг: 0 / 0
Нужна помощь с написанием триггера
    #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
Нужна помощь с написанием триггера
    #40103169
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_dev,

ага, вместо одного триггера две таблицы? Оккама плачет :)
...
Рейтинг: 0 / 0
Нужна помощь с написанием триггера
    #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
Нужна помощь с написанием триггера
    #40103179
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Док,

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

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

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

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

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

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

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


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

изящно. Только мне на клиенте нужно отображать ВСЕ имеющиеся на данный момент у человека телефоны, из которых один является основным :)
...
Рейтинг: 0 / 0
Нужна помощь с написанием триггера
    #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
Нужна помощь с написанием триггера
    #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
Нужна помощь с написанием триггера
    #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
Нужна помощь с написанием триггера
    #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
Нужна помощь с написанием триггера
    #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
Нужна помощь с написанием триггера
    #40103256
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Док
С виду опасностей не вижу...
Твой триггер апдейтит все записи (кроме текущей) с таким же FK_PEOPLE - а достаточно только одной.
Причём делает он это после любого апдейта "главной" записи, даже если MAIN_CONTACT не менялось.

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

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

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

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

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

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


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