要使用嵌套表插入表的Oracle存储过程?

时间:2018-05-11 18:13:23

标签: sql oracle plsql

这个问题有很多答案,但我无法理解它!

我有一个包含嵌套表的表:

    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个城镇?

1 个答案:

答案 0 :(得分:1)

  

"我们如何更改此程序,以便用户可以同时在嵌套表中输入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;
/