Подскажите технику для синхронного добавления записей

Модераторы: kdv, CyberMax

Ответить
frostyland
Сообщения: 38
Зарегистрирован: 05 июл 2007, 13:24

Подскажите технику для синхронного добавления записей

Сообщение frostyland » 23 сен 2008, 14:26

Приветствую.

Возник еще один вопрос.
Есть таблицы:
DEAL - СДЕЛКИ

Код: Выделить всё

CREATE TABLE DEAL(
  DEAL_NO     INTEGER NOT NULL,
  NAME        DEALNAME NOT NULL,
  FK_DEPT_NO  INTEGER
);
ROLES_IN_DEAL - роли в сделке

Код: Выделить всё

CREATE TABLE ROLES_IN_DEAL(
  FK_DEAL INTEGER NOT NULL,
  FK_ROLE INTEGER NOT NULL,
  FK_SOTR INTEGER,
  RATE    DECIMAL(2,2) DEFAULT 0
);
и
ROLES_IN_DEPT - типа шаблонного набора ролей для сделки данного отдела (FK_DEPT)

Код: Выделить всё

CREATE TABLE ROLES_IN_DEPT(
  FK_DEPT INTEGER NOT NULL,
  FK_ROLE INTEGER NOT NULL,
  FK_SOTR INTEGER,
  RATE    DECIMAL(9,2)
);
Логика такая.
При добавлении сделки в таблицу DEAL неплохо бы одновременно с этим копировать в ROLES_IN_DEAL набор шаблонных ролей из ROLES_IN_DEPT, чтобы по умолчанию список ролей для сделки уже автоматически строился.
Удаление и Апдейт решаются ограничениями

Код: Выделить всё

ALTER TABLE ROLES_IN_DEAL ADD CONSTRAINT
FK_RID_DEAL_CONSTRAINT
FOREIGN KEY (FK_DEAL) REFERENCES DEAL (DEAL_NO) 
ON DELETE CASCADE 
ON UPDATE CASCADE;

ALTER TABLE ROLES_IN_DEAL ADD CONSTRAINT
FK_RID_ROLE_CONSTRAINT
FOREIGN KEY (FK_ROLE) REFERENCES THEROLE (ID) 
ON DELETE CASCADE 
ON UPDATE CASCADE;
а автоматическое обновление я попробовал в триггере (уже без курсора а insert ... select :) )

Код: Выделить всё

ALTER TRIGGER TR_DEAL_BI
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
  IF (NEW.DEAL_NO IS NULL) THEN NEW.DEAL_NO = GEN_ID(DEAL_NO_GEN, 1);
  
  INSERT INTO ROLES_IN_DEAL
  (
    FK_DEAL,
    FK_ROLE,
    FK_SOTR,
    RATE
  )
  SELECT
    NEW.DEAL_NO,
    R.FK_ROLE,
    R.FK_SOTR,
    R.RATE
  FROM
    ROLES_IN_DEPT R
  WHERE
    R.FK_DEPT = NEW.FK_DEPT_NO;
END
;
Ничего не вышло по причине того (я так понял), что NEW.DEAL_NO еще неизвестен в табличке ROLES_IN_DEAL, и констрейнт ругнулся.

В after insert невозможно получить ключ только что заинсерченной записи.

Как вообще посоветуете решать такую задачу?

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Re: Подскажите технику для синхронного добавления записей

Сообщение WildSery » 23 сен 2008, 14:39

frostyland писал(а):В after insert невозможно получить ключ только что заинсерченной записи.
Как пробовал?

frostyland
Сообщения: 38
Зарегистрирован: 05 июл 2007, 13:24

Re: Подскажите технику для синхронного добавления записей

Сообщение frostyland » 23 сен 2008, 14:45

WildSery писал(а):
frostyland писал(а):В after insert невозможно получить ключ только что заинсерченной записи.
Как пробовал?
а как там особо пробовать. OLD.* не прокатывает, это только на AFTER UPDATE & AFTER DELETE.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Re: Подскажите технику для синхронного добавления записей

Сообщение WildSery » 23 сен 2008, 14:57

frostyland писал(а):а как там особо пробовать. OLD.* не прокатывает, это только на AFTER UPDATE & AFTER DELETE.
А как же NEW.* ?

frostyland
Сообщения: 38
Зарегистрирован: 05 июл 2007, 13:24

Re: Подскажите технику для синхронного добавления записей

Сообщение frostyland » 23 сен 2008, 15:00

WildSery писал(а):
frostyland писал(а):а как там особо пробовать. OLD.* не прокатывает, это только на AFTER UPDATE & AFTER DELETE.
А как же NEW.* ?
Так ведь AFTER INSERT.
Соответственно

Код: Выделить всё

This column cannot be updated because it is derived from an SQL function or expression.Attempted update of read-only column.
Transaction rolled back.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Re: Подскажите технику для синхронного добавления записей

Сообщение WildSery » 23 сен 2008, 15:03

Ясно.
В триггере BEFORE INSERT заполняй генератором, а в триггере AFTER INSERT только читай.
Мог бы догадаться.

frostyland
Сообщения: 38
Зарегистрирован: 05 июл 2007, 13:24

Re: Подскажите технику для синхронного добавления записей

Сообщение frostyland » 23 сен 2008, 15:13

WildSery писал(а):Ясно.
В триггере BEFORE INSERT заполняй генератором, а в триггере AFTER INSERT только читай.
Мог бы догадаться.
Неясно. Я не могу заполнить в триггере BEFORE INSERT таблицу ROLES_FOR_DEAL.
Триггер уже знает новый номер NEW.DEAL_NO, но я не могу его вставить в ROLES_FOR_DEAL, так как (видимо) запись не закомичена,
и констрейнт,

Код: Выделить всё

ALTER TABLE ROLES_IN_DEAL ADD CONSTRAINT
FK_RID_DEAL_CONSTRAINT
FOREIGN KEY (FK_DEAL) REFERENCES DEAL (DEAL_NO) 
ON DELETE CASCADE 
ON UPDATE CASCADE;
который в этой таблице проверяет соответствие ключей не находит еще этого ключа в DEAL, и ругается. Я так думаю, что ругается именно из-за этого.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Re: Подскажите технику для синхронного добавления записей

Сообщение WildSery » 23 сен 2008, 15:48

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

frostyland
Сообщения: 38
Зарегистрирован: 05 июл 2007, 13:24

Re: Подскажите технику для синхронного добавления записей

Сообщение frostyland » 23 сен 2008, 16:29

Спасибо, все получилось.

Мне стало ясно, что если в AFTER INSERT не получается делать присвоения типа
NEW.FIELD = XXX, то это не означает, что нельзя ими пользоваться в конструкциях типа

Код: Выделить всё

ALTER TRIGGER TR_ADD_ROLES
ACTIVE AFTER INSERT POSITION 0
AS
BEGIN

  INSERT INTO ROLES_IN_DEAL
  (
    FK_DEAL,
    FK_ROLE,
    FK_SOTR,
    RATE
  )
  SELECT
    NEW.DEAL_NO,
    R.FK_ROLE,
    R.FK_SOTR,
    R.RATE
  FROM
    ROLES_IN_DEPT R
  WHERE
    R.FK_DEPT = NEW.FK_DEPT_NO;

END
;

Ответить