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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了要使用嵌套表插入表的Oracle存储过程?相关的知识,希望对你有一定的参考价值。

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

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

    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个城镇输入嵌套表?

答案

鉴于您当前的过程标题传递了两个字符串而没有关于城镇的信息,这应该适合您:

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;

换句话说,您需要使用构造函数来获取单个属性值(参数)并返回对象类型的实例。

另一答案

“我们怎样才能改变这个程序,以便用户可以同时将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;
/

以上是关于要使用嵌套表插入表的Oracle存储过程?的主要内容,如果未能解决你的问题,请参考以下文章

oracle存储过程中临时表的使用,该怎么处理

oracle 怎么在存储过程中创建一个临时表,在里面插入数据,再查找这个临时表的所有数据,最后drop这个表。

oracle存储过程查找表数据插入另一个表中。。

Oracle过程 - 选择所有表,然后循环遍历这些表的记录

ORACLE存储过程创建临时表并插入数据。

用oracle存储过程将一张表的数据查出插入另一张表