在 oracle 中编写一个通用过程

Posted

技术标签:

【中文标题】在 oracle 中编写一个通用过程【英文标题】:writing a generic procedure in oracle 【发布时间】:2009-12-10 10:57:50 【问题描述】:

我想编写以 2 个表的名称作为参数的过程,然后比较 2 个表的数量或行数。 我也想要两列的每个字段。有不匹配的行应该是 移动到另一个错误表。

任何人都可以提供一个 PL/SQL 过程来执行此操作。 我想在 oracle 9 中实现这一点

【问题讨论】:

这两个表是否总是具有完全相同的列定义,是所有表共享一个错误表还是每个表对一个错误表? @david:是的,它们确实有相同的语法 【参考方案1】:

Pablos 的例子行不通,但这个想法是正确的。

像这样做吧。

create or replace PROCEDURE COMPARE_ROW_COUNT(T1 IN VARCHAR2, T2 IN VARCHAR2) AS
  v_r1   number;
  v_r2   number;
  v_sql1  varchar2(200);
  v_sql2  varchar2(200);
BEGIN
  v_sql1 := 'select count(1) from ' || T1;
  v_sql2 := 'select count(1) from ' || T2;
  EXECUTE IMMEDIATE v_sql1 into v_r1;
  EXECUTE IMMEDIATE v_sql2 into v_r2;
  dbms_output.put_line(T1 || ' count = ' || v_r1 || ', ' || T2 || ' count = ' || v_r2);
END;

【讨论】:

@all :感谢您的回复,这是很大的帮助。你能告诉我如何比较这两张表的字段吗?【参考方案2】:

DBMS_SQL 是此类操作的好帮手。

【讨论】:

@ammo: 你能帮我解释一下我的朋友吗?【参考方案3】:

您可以在 PL/SQL 中使用dynamic sqlEXECUTE IMMEDIATE 是你的朋友。

因此,如果您使用两个表名并尝试比较它们的行数,您会执行以下操作:

CREATE OR REPLACE PROCEDURE COMPARE_ROW_COUNT(T1 IN VARCHAR2(200), T2 IN VARCHAR2(200)) AS
  v_cursor integer;
  v_r1   integer;
  v_r2   integer;
  v_sql  varchar2(200);
BEGIN
  v_sql := "select count(1) into :1 from " || T1;
  EXECUTE IMMEDIATE v_sql USING v_r1;
  v_sql := "select count(1) into :1 from " || T2;
  EXECUTE IMMEDIATE v_sql USING v_r2;
  -- compare v_r1 and v_r2
END;

不能 100% 确定 PL/SQL 语法。距离我上次编写出色的 PL/SQL 代码已经有一段时间了!

您可以使用DBMS_SQL 以类似的方法获得相同的结果。不过语法有点复杂。

【讨论】:

绑定变量不能提供表名。【参考方案4】:

我在这里发帖只是为了注意所有答案都围绕动态 SQL,不要将注意力转移到使用它的隐含问题上。 考虑将以下字符串作为第一个或第二个参数传递:

dual where rownum = 0 intersect 
SELECT 0 FROM dual WHERE exists (select 1 from user_sys_privs where UPPER(privilege) = 'DROP USER')

我就这样吧。

回答您的问题 - Oracle 实际上将这些值存储在数据字典中,所以如果您可以访问它:

CREATE OR REPLACE PROCEDURE COMPARE_ROW_COUNT(T1 IN VARCHAR2, T2 IN VARCHAR2) AS
  v_text varchar2(1000);
BEGIN
  select listagg(owner || ' ' || table_name || ' count = ' || num_rows, ',')
   into v_text
   from all_tables --user, all or dba tables depends on requirements
   where table_name in (T1, T2);

 dbms_output.put_line(v_text);

 exception
   when others then raise; -- Put anything here, as long as you have an exception block
END COMPARE_ROW_COUNT;

【讨论】:

以上是关于在 oracle 中编写一个通用过程的主要内容,如果未能解决你的问题,请参考以下文章

Informix 存储过程通用异常处理

求一个通用ORACLE存储过程,实现分页和查询?

oracle 中的通用触发器

spring jdbcTemplate 封装调用存储过程的通用方法(oracle数据库)

如何编写通用 SQL 查询以与所有 RDBMS(Oracle、SQL 服务器、MySql、DB2 等等)兼容的 (YYYY-MM-DD) 形式提取日期

通用Mapper