Хранимая процедура Oracle для вставки в таблицу с вложенной таблицей? - PullRequest
0 голосов
/ 11 мая 2018

Существует несколько ответов на этот вопрос, но я не могу обойти его!

У меня есть таблица, которая содержит вложенную таблицу:

    CREATE OR REPLACE TYPE town_objtyp AS OBJECT (
          townName   VARCHAR,
          population     NUMBER,
          desc    VARCHAR(20),   
          ) 
        /

    CREATE TYPE town_nestedtyp AS TABLE OF town_objtyp 
        /

    CREATE OR REPLACE TYPE country_objtyp AUTHID CURRENT_USER AS OBJECT (
          countryName              CHAR(5),
          continent            VARCHAR,
          town_nested     town_nestedtyp,
          ) 
        /

CREATE TABLE Country_objtab OF Country_objtyp (  
           PRIMARY KEY (countryName)
           )                                          

           NESTED TABLE town_nested STORE AS town_store (     
             (PRIMARY KEY(NESTED_TABLE_ID, townName))              
             ORGANIZATION INDEX COMPRESS)                                                                     
        / 

Поэтому я хочу создать хранимую процедуру, которая позволит пользователю заполнять эту таблицу.

Если бы не было вложенной таблицы, то это было бы просто так:

CREATE OR REPLACE PROCEDURE Add_Country (O_countryName IN CHAR, O_continent IN CHAR)
AS

BEGIN
    DBMS_OUTPUT.PUT_LINE ('Insert attempted');

    INSERT INTO Country_objtab(countryName, continent) 
    VALUES(O_countryName, O_continent);

    DBMS_OUTPUT.PUT_LINE ('Insert succeeded');

      END;
/

Итак, как мы можем изменить эту процедуру, чтобы пользователь мог вводить n городовво вложенную таблицу одновременно?

Ответы [ 2 ]

0 голосов
/ 13 мая 2018

"как мы можем изменить эту процедуру, чтобы пользователь мог одновременно ввести n чисел во вложенную таблицу?"

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

CREATE OR REPLACE PACKAGE pkg_country AS
    PROCEDURE add_country (o_countryname   IN varchar2
                        , o_continent     IN varchar2
                        , p_town_name in varchar2
                        , p_town_pop in varchar2 
                        , p_town_descr in varchar2  );
    PROCEDURE add_town (o_countryname   IN varchar2
                        , p_town_name in varchar2
                        , p_town_pop in varchar2 
                        , p_town_descr in varchar2  );                        
END;
/                        
CREATE OR REPLACE PACKAGE BODY pkg_country AS
    PROCEDURE add_country (o_countryname   IN varchar2
                        , o_continent     IN varchar2
                        , p_town_name in varchar2
                        , p_town_pop in varchar2 
                        , p_town_descr in varchar2  )
    IS
    BEGIN
       INSERT INTO country_objtab VALUES 
       ( NEW country_objtyp (o_countryname,
                             o_continent,
                             NEW town_nestedtyp (
                                new town_objtyp(p_town_name , 
                                                 p_town_pop , 
                                                 p_town_descr ) 
                                )
                            )
                        );
    END  add_country;   

    PROCEDURE add_town (o_countryname   IN varchar2
                        , p_town_name in varchar2
                        , p_town_pop in varchar2 
                        , p_town_descr in varchar2  )
    IS
    BEGIN
      insert into the 
            (select t.town_nested  from Country_objtab t
            where t.countryname  = o_countryname) 
       values ( new town_objtyp(p_town_name , 
                                p_town_pop , 
                                p_town_descr ));
        END  add_town;                                     

END pkg_country;
/

Чтобы создать страну с несколькими городами одновременно, вы можете изменить подпись напринять несколько городских объектов:

CREATE OR REPLACE PACKAGE pkg_country AS
    PROCEDURE add_country (o_countryname   IN varchar2
                        , o_continent     IN varchar2
                        , p_town_1 in town_objtyp := null
                        , p_town_2 in town_objtyp := null
                        , p_town_3 in town_objtyp := null );
    PROCEDURE add_town (o_countryname   IN varchar2
                        , p_town in town_objtyp  );
END;
/                        
CREATE OR REPLACE PACKAGE BODY pkg_country AS
    PROCEDURE add_country (o_countryname   IN varchar2
                        , o_continent     IN varchar2
                        , p_town_1 in town_objtyp := null
                        , p_town_2 in town_objtyp := null
                        , p_town_3 in town_objtyp := null  )
    IS
        l_towns town_nestedtyp := new town_nestedtyp();
    BEGIN
       if p_town_1 is not null then
           l_towns.extend();
           l_towns(l_towns.count()) := p_town_1;
       end if;
       if p_town_2 is not null then
           l_towns.extend();
           l_towns(l_towns.count()) := p_town_2;
       end if;
       if p_town_3 is not null then
           l_towns.extend();
           l_towns(l_towns.count()) := p_town_3;
       end if;

       INSERT INTO country_objtab VALUES 
       ( NEW country_objtyp (o_countryname,
                             o_continent,
                             l_towns
                            )
                        );
    END  add_country;   

    PROCEDURE add_town (o_countryname   IN varchar2
                        , p_town_name in varchar2
                        , p_town_pop in varchar2 
                        , p_town_descr in varchar2  )
    IS
    BEGIN
      insert into the 
            (select t.town_nested  from Country_objtab t
            where t.countryname  = o_countryname) 
       values ( new town_objtyp(p_town_name , 
                                p_town_pop , 
                                p_town_descr ));

    END  add_town;                                     

END pkg_country;
/

Это явно неуклюжий интерфейс и неуклюжая реализация.Также это накладывает искусственное и нежелательное ограничение на количество городов, которые могут быть включены в первый звонок.Итак, что вам нужно сделать, это перенести массив в вызывающую программу:

CREATE OR REPLACE PACKAGE pkg_country AS
    PROCEDURE add_country (o_countryname   IN varchar2
                        , o_continent     IN varchar2
                        , p_towns in town_nestedtyp);
    PROCEDURE add_town (o_countryname   IN varchar2
                        , p_town in town_objtyp  );

END;
/                        
CREATE OR REPLACE PACKAGE BODY pkg_country AS
    PROCEDURE add_country (o_countryname   IN varchar2
                        , o_continent     IN varchar2
                        , p_town_1 in town_objtyp := null
                        , p_town_2 in town_objtyp := null
                        , p_town_3 in town_objtyp := null  )
    IS
    BEGIN

       INSERT INTO country_objtab VALUES 
       ( NEW country_objtyp (o_countryname,
                             o_continent,
                             p_towns
                            )
                        );
    END  add_country;   

    PROCEDURE add_town (o_countryname   IN varchar2
                        , p_town_name in varchar2
                        , p_town_pop in varchar2 
                        , p_town_descr in varchar2  )
    IS
    BEGIN
      insert into the 
            (select t.town_nested  from Country_objtab t
            where t.countryname  = o_countryname) 
       values ( new town_objtyp(p_town_name , 
                                p_town_pop , 
                                p_town_descr ));

    END  add_town;                                     

END pkg_country;
/
0 голосов
/ 11 мая 2018

Учитывая, что ваш текущий заголовок процедуры передается в две строки и нет информации о городах, это должно работать для вас:

CREATE OR REPLACE PROCEDURE add_country (o_countryname   IN varchar2,
                                         o_continent     IN varchar2)
AS
BEGIN
   DBMS_OUTPUT.put_line ('Insert attempted');

   INSERT INTO country_objtab (countryname, continent)
           VALUES (
                     NEW country_objtyp (o_countryname,
                                         o_continent,
                                         NEW town_nestedtyp ()));

   DBMS_OUTPUT.put_line ('Insert succeeded');
END;

Другими словами, вам нужно использовать функцию конструктора для получения значений отдельных атрибутов.(параметры) и возвращают экземпляр типа объекта.

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