我有一个包含大量INSERT的大型存储过程。有许多INSERTS几乎相同 - 它们因某些参数而不同(所有INSERT到同一个表)
有没有办法创建一个函数/方法,我将传递上述参数,函数/方法将生成具体的INSERT?
由于
答案 0 :(得分:5)
不确定。创建私有函数很容易。
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>
编辑2
如果您真的想要执行私有函数,那么您可以将%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 :(得分:1)
你可以使用这样的东西
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
找到here
答案 2 :(得分:0)
包内:
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;
这符合您问题中列出的要求。确保你做得恰当。 您可以更改参数列表以基于表接收记录,并在插入中插入记录而不是所有单个列。个人选择。