Вызов «функции» внутри хранимой процедуры - PullRequest
1 голос
/ 08 апреля 2010

У меня есть большая хранимая процедура, которая содержит много вставок. Есть много ВСТАВКИ, которые почти идентичны - они отличаются по некоторым параметрам (все ВСТАВКИ в одну и ту же таблицу)

Есть ли способ создать функцию / метод, которому я передам вышеупомянутые параметры, и функция / метод будет генерировать конкретные вставки?

Спасибо

Ответы [ 3 ]

5 голосов
/ 08 апреля 2010

Конечно.Создать личную функцию легко.

create or replace procedure p1 as

    n pls_integer;

    function private_f return number is
    begin
        return n;
    end private_f;
begin
    n := private_f;
end p1;

Следует обратить внимание на то, что частные процедуры и определения функций должны быть последними объявлениями в блоке declare.То есть мы не можем объявить какие-либо переменные между закрытой функцией и предложением begin внешней процедуры.

Я не показал вам, как реализовать закрытую функцию, которая вставляет строку в таблицу.Это потому, что это плохой способ делать вещи.Более эффективно использовать SQL на основе множеств.

Вы не говорите, откуда берутся параметры, поэтому я что-нибудь придумаю.

рабочий пример

Эта процедура эмулирует ETLпроцесс.Он берет некоторые данные из промежуточной таблицы и загружает их в коллекцию PL / SQL.Затем он каким-то образом манипулирует загруженными данными, а затем использует оператор массовой вставки для помещения данных в целевую таблицу.

SQL> create or replace procedure pop_emps
  2      ( p_mgr in emp.mgr%type)
  3  as
  4      type emp_nt is table of emp%rowtype;
  5      new_emps emp_nt;
  6  begin
  7      --  populate array from staging table
  8      select emp_seq.nextval
  9             , t.ename
 10             , t.job
 11             , p_mgr
 12             , trunc(sysdate)
 13             , t.sal
 14             , null
 15             , t.deptno
 16      bulk collect into new_emps
 17      from emp_import t;
 18      -- fix some special values
 19      for i in new_emps.first..new_emps.last
 20      loop
 21          if new_emps(i).deptno = 50
 22          then
 23              new_emps(i).job := 'PLUMBER';
 24              new_emps(i).mgr := 8061;
 25          end if;
 26      end loop;
 27      --  insert new rows into EMP table
 28      forall j in new_emps.first..new_emps.last
 29          insert into emp
 30              values new_emps(j);
 31  end  pop_emps;
 32  /

Procedure created.

SQL>

Обратите внимание, что FORALL - это заданная операция , а не цикл .

Во всяком случае, чтобы показать, как это работает, я загружу эти три строки ...

SQL> select * from emp_import
  2  /

ENAME                       SAL     DEPTNO JOB
-------------------- ---------- ---------- --------------------
KESTELYN                   3500         30 MARKETING
LIRA                       3750         30 MARKETING
TRICHLER                   3500         50 MARKETING

SQL> exec pop_emps(7839)

PL/SQL procedure successfully completed.

SQL> select * from emp where hiredate = trunc(sysdate)
  2  /

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
      8083 KESTELYN   MARKETING       7839 08-APR-10       3500                    30
      8084 LIRA       MARKETING       7839 08-APR-10       3750                    30
      8085 TRICHLER   PLUMBER         8061 08-APR-10       3500                    50

SQL>

edit 2

Если вы действительно хотите сделатьприватная функция thang, тогда вы можете передать% ROWTYPE в качестве параметра ....

create or replace procedure pop_emps is
    new_row emp%rowtype;
    procedure pop_emp_row
        ( p_row in emp%rowtype)
    is 
    begin
        insert into emp
            values p_row;
    end pop_emp_row;
begin

    -- assign some values to new_row
    new_row.empno := emp_seq.nextval;
    new_row.ename := 'WHOEVER';
    new_row.hiredate := trunc(sysdate);
    -- etc, etc

    pop_emp_row(new_row);
end  pop_emps;
/
1 голос
/ 08 апреля 2010

вы можете использовать что-то вроде этого

CREATE FUNCTION WEIGHTED_AVERAGE3 (n1 INT,n2 INT,n3 INT,n4 INT,v1 VARCHAR(50))
  RETURNS INT
  DETERMINISTIC
   BEGIN
    DECLARE i1,i2,i3,i4,avg INT;
    INSERT INTO sfdata VALUES(n1,n2,n3,n4,v1);
    RETURN 1;
   END|
Query OK, 0 rows affected (0.08 sec)
mysql> SELECT WEIGHTED_AVERAGE3(50,60,60,50,'Thoko')\G
*************************** 1. row ***************************
WEIGHTED_AVERAGE3(50,60,60,50,'Thoko'): 1
1 row in set (0.00 sec)
mysql> SELECT * FROM sfdata\G

но лучше использовать как хранимую процедуру, вот так

DROP PROCEDURE IF EXISTS `sp_students_INSERT_byPK` 
GO

CREATE PROCEDURE sp_students_INSERT_byPK
     (
        IN  p_student_id                    INT(11)       , 
        IN  p_password                      VARCHAR(15)   , 
        IN  p_active_flg                    TINYINT(4)    , 
        IN  p_lastname                      VARCHAR(30)   , 
        IN  p_firstname                     VARCHAR(20)   , 
        IN  p_gender_code                   VARCHAR(1)    ,
        IN  p_is_on_staff                   TINYINT(4)    , 
        IN  p_birth_dttm                    DATETIME        
     )
BEGIN 

    INSERT INTO students
         (
           student_id                    , 
           password                      , 
           active_flg                    , 
           lastname                      , 
           firstname                     , 
           gender_code                   ,
           is_on_staff                   , 
           birth_dttm                    
         )
    VALUES 
         ( 
           p_student_id                    , 
           p_password                      , 
           p_active_flg                    , 
           p_lastname                      , 
           p_firstname                     , 
           p_gender_code                   , 
           p_is_on_staff                   ,
           p_birth_dttm                    
         ) ; 
END 

GO

найдено здесь

0 голосов
/ 16 апреля 2010

Внутри упаковки:

 PROCEDURE do_insert(parameter_1_i IN  table_name.column_name1%TYPE
                    ,parameter_2_i IN  table_name.column_name2%TYPE
                    ,parameter_3_i IN  table_name.column_name3%TYPE
                    ... all of the table column names here
                    )  
 IS
   /*  
   || Add proper exception handling to this procedure.
   */ 
   BEGIN   
     INSERT  
       INTO table_name  
          ( column_name1  
          , column_name2  
          , column_name3
          )  
    VALUES( parameter_1_i  
          , parameter_2_i  
          , parameter_3_i  
          ... all of the parameters, some will have the value of NULL  
          )  
   END do_insert;

Это соответствует вашим требованиям, перечисленным в вашем вопросе. Убедитесь, что вы делаете соответствующие действия. Вы можете изменить список параметров, чтобы получить запись на основе таблицы и выполнить вставку с записью в вставке вместо всех отдельных столбцов. Личный выбор.

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