Алгоритм выбора таблицы - PullRequest
2 голосов
/ 15 июня 2010

Ниже я использую простой пример, реальные таблицы больше, я не могу хранить устройства в одной таблице, я не могу объединить таблицы device1 и device2.

У меня есть три таблицы: устройство1, устройство2, компьютер (устройство3), устройство1 и устройство2 имеют идентификаторы из одной и той же последовательности, устройство3 - это компьютер. Таблица device3 может быть связана с device1 и device2 (многие-ко-многим), поэтому у меня есть две таблицы с отношениями: rel1with3 и rel2with3.

CREATE SEQUENCE device_1or2;
CREATE SEQUENCE device_3;

CREATE TABLE device1 
  ( d_id NUMBER, d_data VARCHAR2(20)
  , CONSTRAINT device1_pk PRIMARY KEY (d_id));
CREATE TABLE device2 
  ( d_id NUMBER, d_data VARCHAR2(20)
  , CONSTRAINT device2_pk PRIMARY KEY (d_id));
CREATE TABLE computer
  ( d_id NUMBER, d_data VARCHAR2(20)
  , CONSTRAINT device3_pk PRIMARY KEY (d_id));

CREATE TABLE rel1with3 
  ( d_id_1 NUMBER, d_id_3 NUMBER
  , CONSTRAINT rel13_fk_1 FOREIGN KEY (d_id_1) REFERENCES device1 (d_id)
  , CONSTRAINT rel13_fk_3 FOREIGN KEY (d_id_3) REFERENCES computer (d_id)
);
CREATE UNIQUE INDEX I_REL_13 ON rel1with3 (d_id_1, d_id_3);

CREATE TABLE rel2with3 
( d_id_2 NUMBER, d_id_3 NUMBER
, CONSTRAINT rel23_fk_2 FOREIGN KEY (d_id_2) REFERENCES device2 (d_id)
, CONSTRAINT rel23_fk_3 FOREIGN KEY (d_id_3) REFERENCES computer (d_id)
);
CREATE UNIQUE INDEX I_REL_23 ON rel2with3 (d_id_2, d_id_3);

Я хочу создать хранимую процедуру с двумя параметрами (устройство1 или устройство2 в качестве первого параметра, компьютер в качестве второго) и добавить / удалить отношение (вставить / удалить строку в таблице отношений).

CREATE OR REPLACE PROCEDURE Add_Relation
( COMPUTER NUMBER
, DEVICE   NUMBER
, ERR      OUT NUMBER
) IS
    PRAGMA AUTONOMOUS_TRANSACTION;
    device_data VARCHAR2(20);
BEGIN
  -- detect which device it is, insert record
  -- stored procedure, the same for both device type, BUT uses device data from additional table field
  WRITE_LOG(device, device_data, computer);
  COMMIT;
  EXCEPTION
    WHEN OTHERS THEN ERR := TO_CHAR(SQLCODE);
END;

Вопрос: КАК лучше организовать это? Используете другую функцию? Используя IF-ELSE? Как быстрее выполнить и т.д.?

Ответы [ 2 ]

1 голос
/ 15 июня 2010

Я бы просто попытался вставить в rel1with3, если это не удалось, попробуйте с rel2with3:

CREATE OR REPLACE PROCEDURE Add_Relation(computer NUMBER, device NUMBER) IS
   device_data VARCHAR2(20);
   parent_key_not_found EXCEPTION;
   PRAGMA EXCEPTION_INIT(parent_key_not_found, -2291);
BEGIN
   BEGIN
      INSERT INTO rel1with3 (d_id_1, d_id_3) VALUES (computer, device);
      device_data := 'device1';
   EXCEPTION
      WHEN parent_key_not_found THEN
         INSERT INTO rel2with3 (d_id_2, d_id_3) VALUES (computer, device);
         device_data := 'device2';
   END;
   WRITE_LOG(device, device_data, computer);
END;

Несколько предложений:

  1. использовать исключения PL / SQL вместо возвращаемых параметров (вы можете легко забыть проверить параметры, что приводит к трудным для диагностики ошибкам) ​​
  2. не используйте автономные транзакции, если у вас нет необходимости их использовать (в этом случае они нарушат ваш поток транзакций).
  3. использовать процессы транзакции (commit / rollback) только в верхней вызывающей процедуре / коде (обычно вызывающее приложение, а не PL / SQL)
  4. не забудьте проиндексировать оба ссылающихся столбца на rel1with3 и rel2with3 (обычно у вас будет PK на (d_id_1, d_id_3), поэтому вам потребуется дополнительный индекс на d_id_3)
1 голос
/ 15 июня 2010

Я бы просто использовал один объект последовательности и имел бы одну таблицу устройств.В таблице устройств это будет выглядеть следующим образом:

CREATE TABLE device
(
   ID NUMBER NOT NULL PRIMARY KEY
 , device_name VARCHAR2(100) NOT NULL
 , device_type VARCHAR2(100) NOT NULL
 , parent_device_id NUMBER NULL
 , child_device_id NUMBER NULL
);

alter table device
  add constraint FK1 foreign key (parent_device_id)
  references device (ID);

alter table device
  add constraint FK2 foreign key (child_device_id)
  references device (ID);

Для устройств типа 3 (многие-ко-многим) у вас будут значения для parent_device_id и child_device_id (это будут устройства, которыеустройство 3 подключено к).Если нет никаких устройств, связанных с этим устройством, то эти столбцы будут нулевыми для данного устройства.

Если имя лучше, чем parent / child, вы можете использовать все, что нужно.Идея состоит в том, что вы просто сохраняете устройства в одной таблице и соответственно отображаете отношения.

parent_device_id и child_device_id будут иметь внешние ключи обратно в таблицу устройств в столбце id, чтобы вы никогда не потеряли"любые записи устройства.

Вы можете использовать тот же объект последовательности для создания новых идентификаторов при вставке записей устройства.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...