2010-04-08 5 views
1

J'ai une grosse procédure stockée qui contient beaucoup d'INSERT. Il y a beaucoup d'INSERTS qui sont presque identiques - ils sont différents par certains paramètres (tous les INSERTs à la même table)Appel de "fonction" à l'intérieur d'une procédure stockée

Existe-t-il un moyen de créer une fonction/méthode, à laquelle je vais passer le paramètre ci-dessus (s) et la fonction/méthode va générer des INSERT concrets?

Remerciements

Répondre

5

Sûr. Il est facile de créer une fonction privée.

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; 

La chose à surveiller est que la procédure privée et définitions fonction doit être les dernières déclarations dans le bloc declare. Autrement dit, nous ne pouvons pas déclarer de variables entre une fonction privée et la clause begin de la procédure externe.

Je ne vous ai pas montré comment implémenter une fonction privée qui insère une ligne dans une table. C'est parce que c'est une mauvaise façon de faire les choses. Il est plus efficace d'utiliser SQL dans un ensemble basé sur l'ensemble.

Vous ne dites pas d'où proviennent les paramètres, alors je vais faire quelque chose.

exemple travaillé

Cette procédure émule un processus ETL. Il prend des données d'une table de transfert et les transfère dans une collection PL/SQL. Il manipule ensuite les données chargées d'une certaine manière, puis utilise une instruction d'insertion en bloc pour placer les données dans la table cible.

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> 

Notez que FORALL est une opération de jeu pas une boucle.

Quoi qu'il en soit, pour montrer qu'il fonctionne, je vais charger ces trois lignes ...

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> 

modifier 2

Si vous voulez vraiment faire la fonction privée thang, alors vous pouvez passer une % ROWTYPE comme paramètre ....

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

vous pouvez utiliser quelque chose comme ça

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 

mais il est mieux utilisé comme une procédure stockée, comme si

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 

trouvé here

+0

Ceci est la syntaxe de MySQL, donc il ne sera pas compilé sur Oracle. – APC

0

A l'intérieur d'un paquet:

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; 

Cela répond à vos exigences énumérées dans votre question. Assurez-vous de vous engager de manière appropriée. Vous pouvez modifier la liste de paramètres pour recevoir un enregistrement basé sur la table et insérer une insertion avec l'enregistrement dans l'insertion au lieu de toutes les colonnes individuelles. Choix personnel.

Questions connexes