【问题标题】:ORACLE SQL: Looping over tableORACLE SQL:循环遍历表
【发布时间】:2018-12-06 11:27:53
【问题描述】:

我有一个包含表名列表的表。 我想一一搜索这些表中的每一个,看看它们是否包含特定元素(主键,在脚本开头指定)。 我想返回该元素存在的所有表的列表(理想情况下是不同的)。 我对这个 PL/SQL“不仅仅是一个查询”的东西还很陌生。所以我提前为你即将看到的残暴尝试道歉,但希望它说明了我的目标:

PROCEDURE CHECK_FOR_ELEMENTS
BEGIN
DECLARE 
ELEMENT_KEY varchar(5):=X78ehryfk;
RNUM_MAX int :=167;

----create output table for script
create or replace table ALL_TABLES CONTAINING_&ELEMENT_KEY 
(ELEMENT_KEY VARCHAR(255), 
TABLE_NAME varchar(255))
/
commit;

---begin loop over rnum;
FOR rnum_counter in 1..&RNUM_MAX
LOOP
--define this statement as variable TABLE_NAME_VAR
select table_name from (select * from (select table_name, rownum as rnum         
from all_tables
where owner = 'RMS'
and table_name like 'ABC%'
and table_name not like '%STG'
and table_name not like '%BKP'
and num_rows>0
order by num_rows desc)
where rnum = rnum_counter
)INTO TABLE_NAME_VAR
;
----run below to collect row, if it exists, from table being searched
SQL_STMT:='INSERT INTO ALL_TABLES CONTAINING_&ELEMENT_KEY 
SELECT distinct key,'||TABLE_NAME_VAR||' as UMF from         
'||TABLE_NAME_VAR|| 
' where key like 'ELEMENT_KEY-%'
execute immediate SQL_STMT;
commit;
---insert row into table created for output

END LOOP
---loop over all tables

END;

我得到的主要错误信息是 TABLE_NAME_VAR 不是动态 SQL 语句中的有效表名。我用谷歌搜索了一下,现在我明白你不能使用变量以这种方式输入表名。

非常感谢任何帮助! 谢谢!

【问题讨论】:

  • 如果你只运行 select 语句会发生什么,我假设会产生错误? SELECT distinct voyage_key,'||TABLE_NAME_VAR||'作为来自 '||TABLE_NAME_VAR|| 的 UMF
  • 是的,我收到以下错误消息:ORA-00903: invalid table name 00903. 00000 - "invalid table name" *Cause: *Action:
  • 根本不喜欢这种方法,但您需要使用立即执行并在您的过程中构建 DDL 字符串。
  • @tbone,谢谢,我也不喜欢我的方法,因为它不起作用。但我对 SQL 的了解有限,这应该归咎于我。很抱歉,我不太确定 DDL 字符串是什么,但我会用谷歌搜索,看看我得到了什么。
  • DDL 是数据定义语言,基本上是您的“创建表”语句。

标签: sql oracle loops plsql


【解决方案1】:

在这里,我试图为您清理它。如果您仍然遇到错误,请告诉我。

create or replace PROCEDURE CHECK_FOR_ELEMENTS is
    ELEMENT_KEY varchar2(14):='X78ehryfk';
    RNUM_MAX int :=167;
    TABLE_NAME_VAR varchar2(30);
    SQL_STMT varchar2(4000);
BEGIN

----create output table for script
begin
    execute immediate 'drop table ALL_TABLES_WITH_' || element_key;
exception when others then null;
end;
execute immediate 'create table ALL_TABLES_WITH_' || element_key || ' 
(ELEMENT_KEY VARCHAR2(255), -- does this need to be 255 characters?
TABLE_NAME varchar2(30))';

--- implicit cursor loop
FOR rnum_row in (select table_name, rownum as rnum         
    from all_tables
    where owner = 'RMS'
    and table_name like 'ABC%'
    and table_name not like '%STG'
    and table_name not like '%BKP'
    and num_rows>0
    order by num_rows desc)
LOOP
    if rnum_row.rnum > RNUM_MAX 
        then exit;
    end if;

    TABLE_NAME_VAR := rnum_row.table_name;

    ----run below to collect row, if it exists, from table being searched
    SQL_STMT:='INSERT INTO ALL_TABLES_WITH_' || element_key || ' 
    (ELEMENT_KEY, TABLE_NAME)
    SELECT distinct key, :1 as UMF from         
    '||TABLE_NAME_VAR|| 
    ' where key like :2';
    execute immediate SQL_STMT using TABLE_NAME_VAR, element_key || '-%';

    ---insert row into table created for output
END LOOP;
commit; 
---loop over all tables

END CHECK_FOR_ELEMENTS;
/

【讨论】:

  • 鉴于element_key 被定义为VARCHAR(255),ALL_TABLES_WITH_' || element_key 很有可能会违反 Oracle 名称长度限制(即使使用 Oracle 12cR2 扩展名称功能。
  • 是的,好点。 OP 将其定义为varchar2(5)(对于给定的字符串来说太小了),所以我对其进行了编辑并将其更改为 varchar2(14),因为任何大于此值的内容都会违反使用前缀 @987654326 的基本 30 个字符名称限制@.
  • 谢谢!它编译! :D 现在唯一的问题是如何访问包含结果的表....它说当我之后尝试查询时该表不存在。 @kfinity
  • 嗯,你可以select * from user_tables搜索。你是在编译后运行程序吗? exec check_for_elements;
  • 我正在查看create table 语句中的列声明。但是你的代码是有效的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多