Oracle 存储过程自动化

Posted

技术标签:

【中文标题】Oracle 存储过程自动化【英文标题】:Oracle Store Procedures Automation 【发布时间】:2010-12-03 06:57:33 【问题描述】:

我目前正在研究在 oracle DB 中自动创建存储过程和函数的过程 我正在使用 java 来自动化创建存储过程的过程,这样当我给出表名时,java 代码将生成以下过程:

选择 插入 更新 删除

并将它们放在文本文件中

例如

select * from emp where emp_id=i_emp_id and emp_nm=i_emp_nm and emp_dpt=i_emp_dpt

如果所有三个输入都不为空,它的功能应该像

select * from emp where emp_id=i_emp_id and emp_nm=i_emp_nm and emp_dpt=i_emp_dpt

如果我将 i_emp_id 作为 null 传递,那么查询应该像这样运行

select * from emp where emp_nm=i_emp_nm and emp_dpt=i_emp_dpt

如果我将 i_emp_id 作为 null 并将 i_emp_dpt 作为 null 传递,那么查询应该像这样运行

select * from emp where emp_nm=i_emp_nm

类似的更新等

我有already posted a question on this

你能不能给我一些一般性的查询 选择 插入 更新 并删除

我对存储过程的输入可能会变化为空值或实际值

【问题讨论】:

【参考方案1】:

Table API 的问题是有问题的。一方面,它们可以防止 SQL 语句嵌入到整个应用程序中。另一方面,它们会导致一种不良实践文化,因为它们使开发人员无法真正了解数据库。

无论哪种方式,这都是您要完成的大量工作。它需要对 Oracle、SQL 和 PL/SQL 有很多了解才能正确完成。一个不完整的解决方案将毫无用处。也许比没用更糟糕。

所以,不要自己写这个。领先的 PL/SQL 专家 Steven Feuerstein 编写了一个复杂的实用程序来生成表 API:Quest Code Generation Utility(以前称为 QNXO)。它在 Quest 网站上是免费的。 Find it here。确实它不是用 Java 编写的,但那又怎样?

【讨论】:

但就我的知识和理解而言,我仍然需要知道这些事情。谢谢你的链接 @Aravind - 但首先您需要对 Oracle SQL 有足够的了解才能评估您收到的任何回复。这就是我在回答你的另一个问题时提出的观点。【参考方案2】:

我不确定你想要的东西是否有用,但如果你想生成插入、更新或删除语句,最好了解视图 all_tab_columns 和 user_tab_columns。

插入示例:

select 'insert into ' || :table_name || ' (' qry
from   dual
union all
select column_name || ', '
from   user_tab_columns
where  table_name = :table_name
union all
select ') values ('
from   dual
union all
select ':' || column_name || ', '
from   user_tab_columns
where  table_name = :table_name
union all
select ')'
from   dual

【讨论】:

【参考方案3】:

有很多方法可以解决这个问题。

一种解决方案是overload different code,具体取决于参数的数量及其类型。

另一种解决方案是使用一组固定的参数,而不是过滤空值......

select * 
from emp 
where emp_id=NVL(i_emp_id, emp_id) 
and emp_nm=NVL(i_emp_nm, emp_nm) 
and emp_dpt=NVL(i_emp_dpt, emp_dpt);

或者您可以在 PL/SQL 中将查询创建为字符串并使用“EXECUTE IMMEDIATE”....

PROCEDURE finder (
      i_emp_id IN emp.emp_id%TYPE,
      i_emp_nm IN emp.emp_nm%TYPE DEFAULT NULL,
      i_emp_dpt IN emp.emp_dpt%TYPE DEFAULT NULL,
      .... 
   )
IS
   l_qry VARCHAR2(1000) := 'SELECT * FROM emp WHERE 1=1';
BEGIN
   IF (i_emp_nm IS NOT NULL ) 
   THEN
      l_qry := l_qry || ' AND emp_nm=' || i_emp_nm;
   IF (i_emp_dpt IS NOT NULL )
   THEN
      l_qry := l_qry || ' AND emp_dpt=' || i_emp_dpt;
   EXECUTE IMMEDIATE l_qry;
....

【讨论】:

两种提议的解决方案都代表了不好的做法。如果任何谓词列包含 null,第一个将返回错误的结果。第二个不使用绑定变量,这会导致 OLTP 系统的性能非常差。请参阅我对 Aravind 的其他问题的回答,了解正确的方法。

以上是关于Oracle 存储过程自动化的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 存储过程自动化

在 oracle 中执行存储过程后是不是发生任何自动提交?

oracle存储过程中循环调用存储过程

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

数据治理中Oracle SQL和存储过程的数据血缘分析

如何让oracle job定时调用一个有参的存储过程