Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 Вставка данных в несколько таблиц  [new]
Serg Kutuzov
Member

Откуда: Хабаровск
Сообщений: 43
Сразу скажу - новичок в Oracle. Есть задача хранить навигационные данные, поступающие от нескольких систем навигации из БД разного типа. Пишу клиент забора данных из этих систем в БД Oracle на C++Builder.
Будут такие таблички в Oracle:

/*----Справочник систем навигации, зарегистрированных в системе----*/
create table "NavigationSystems"  (
  "NavSystemID"  INTEGER   not null, /* Код системы навигации*/
  "NameNavSystem"   CHAR(2   not null, /*Название навигационной системы*/
  "Note"               CHAR(255), /*Примечание*/
  constraint PK_NAVIGATIONSYSTEMS primary key ("NavSystemID")
);
create unique index "NavigationSystems_PK" on "NavigationSystems" (
  "NavSystemID" ASC
);

/*----Таблица со сквозной нумерацией всех модемов в навигационной базе----*/
create table "UniqueModemNumbers"  (
  "UniqueModemNumber"  INTEGER not null, /*Уникальный номер модема в нашей системе*/
  "NavSystemID"        INTEGER   not null,/*Код системы навигации*/
  "ModemNumber"        INTEGER not null,  /*Номер модема в конкретной системе навигации*/
constraint PK_UNIQUEMODEMNUMBERS primary key ("UniqueModemNumber")
);
create unique index "UniqueModemNumbers_PK" on "UniqueModemNumbers" (
  "UniqueModemNumber" ASC
);
create index "Код системы навигации_FK" on "UniqueModemNumbers" (
  "NavSystemID" ASC
);
alter table "UniqueModemNumbers"
  add constraint "FK_UNIQUEMO_КОД СИСТЕ_NAVIGATI" foreign key ("NavSystemID")
     references "NavigationSystems" ("NavSystemID");

/*----Журнал полученных пакетов ----*/
create table "PacketsLog"  (
  "UniquePacketNumber" INTEGER    not null, /*Уникальный номер пакета*/
  "UniqueModemNumber"  INTEGER  not null,/*Уникальный номер модема в нашей системе*/
  "Curr_DatePacket"    TIMESTAMP   not null, /*Дата прихода пакета*/
  constraint PK_PACKETSLOG primary key ("UniquePacketNumber")
);
create unique index "PacketsLog_PK" on "PacketsLog" (
  "UniquePacketNumber" ASC
);
create index "Relationship_5_FK" on "PacketsLog" (
  "UniqueModemNumber" ASC
);
alter table "PacketsLog"
  add constraint FK_PACKETSL_RELATIONS_UNIQUEMO foreign key ("UniqueModemNumber")
     references "UniqueModemNumbers" ("UniqueModemNumber");
/* Значения датчиков модемов в пришедших пакетах навигационных систем*/
create table "SensorsData"  (
  "UniquePacketNumber" INTEGER  not null, /*Уникальный номер пакета*/
  "SensorNumber"       INTEGER   not null, /*Номер сенсора модема*/
  "SensorValue"        INTEGER   not null,/*Значение сенсора*/
  "SensorStatus"       INTEGER   not null,/*Состояние сенсора*/
  constraint PK_SENSORSDATA primary key ("UniquePacketNumber", "SensorNumber")
);
create unique index "SensorsData_PK" on "SensorsData" (
  "UniquePacketNumber" ASC,
  "SensorNumber" ASC
);
create index "Relationship_4_FK" on "SensorsData" (
  "UniquePacketNumber" ASC
);
alter table "SensorsData"
  add constraint FK_SENSORSD_RELATIONS_PACKETSL foreign key ("UniquePacketNumber")
     references "PacketsLog" ("UniquePacketNumber");
Пакет содержит в себе следующие данные:
  • Номер модема в конкретной системе,
  • Номер системы,
  • Дата прихода пакета,
  • Данные со значениями датчиков (номер датчика, значение датчика, статус датчика).
    Алгорит вставки мой:
  • Начинаем транзакцию
  • Вызываем хранимую процедуру, передавая в неё (номер модема, номер системы, дату получения пакета).
    create or replace function "AddPacket"(in_ModemNumber integer,
      in_NavSystemID integer, in_DatePacket integer) return integer as
    declare
        ret_UniquePacketNumber integer;
    begin
        ret_UniquePacketNumber := my_seq.nextval;
        INSERT INTO PacketsLog VALUES(ret_UniquePacketNumber, 
          (SELECT UniqueModemNumber FROM UniqueModemNumbers 
           WHERE (NavSystemID = in_NavSystemID) and
                 (ModemNumber = in_ModemNumber)), in_DatePacket);
        return ret_UniquePacketNumber;
    end;
    
  • Процедура через запрос получает "уникальный номер модема в системе".
  • Процедура используя выделенный Sequence генерирует "уникальный номер модема в системе".
  • Процедура заносит данные о пакете в таблицу "PacketsLog", возвращая "уникальный номер модема в системе".
  • Серией запросов записываем значения датчиков в таблицу "SensorsData"
    INSERT INTO SensorData VALUES(?in_UniquePacketNumber, ?in_SensorNumber, ?in_SensorValue, ?in_SensorStatus);
    
  • Подтверждаем транзакцию,
  • Если пакет c таким "уникальным номером" и "датой" уже зарегистрирован в системе, то будет откат транзакции (сработает индекс SensorsData_PK) и данные пакета не занесутся в обе таблицы, иначе всё ок.

    Уф, надеюсь нормально объяснил, что хочу сделать.
    А теперь вопрос, насколько правильно я это сделал?
    Как это можно сделать поэлегантней, ведь у меня возможный откат транзакции идёт на первом запросе занесения в первую таблицу, т.е. запросы на заполнение таблицы сыпятся впустую?
    Просто частота запросов на обновление данных из внешних баз где-то раз в 5 сек. А модемов всех систем в совокупности может быть около 1000. При этом примерно по 5 датчиков на модем. Т.е. я зря заношу 5 записей во вторую таблицу. Или может лучше сначала проверять, есть ли такая комбинация (уникальный номер модема, дата прихода пакета) уже в системе?
  • 13 авг 09, 09:37    [7531371]     Ответить | Цитировать Сообщить модератору
     Re: Вставка данных в несколько таблиц  [new]
    suPPLer
    Member

    Откуда: Харків, Україна
    Сообщений: 7794
    Блог
    Serg Kutuzov,

    0. RTFM RETURNING INTO clause.
    1. RTFM Exception Definition.
    2. RTFM DUP_VAL_ON_INDEX.
    3. В обработке исключения DUP_VAL_ON_INDEX возвращайте null из функции, а в клиенте проверяйте результат на null. И если уже вернулось что-то нормальное - тогда начинайте вставки...

    PS: А вообще ещё Вам хорошо про коллекции почитать и FORALL-инструкцию. Собирали бы Ваши показания датчиков в коллекции, передавали процедурам и вставляли их пачкой, а не по одной записи.
    13 авг 09, 13:55    [7533431]     Ответить | Цитировать Сообщить модератору
    Все форумы / Oracle Ответить