2017-04-05 1697 views
0

我有一个接收参数为where子句(即where col1 = 1)的过程。我使用这个子句在一些表中使用EXECUTE IMMEDIATE语句搜索并将结果插入到嵌套表中,而不是显示。“ORA-01007:变量不在选择列表中”当没有行由EXECUTE IMMEDIATE返回时

如果找到任何数据,该过程将正常工作,但如果未找到数据,则会引发上述错误。

有人可以解释是什么原因导致这个错误吗?

下面是该过程:

create or replace procedure prc_checks(pi_where varchar2) as 

    cursor c_tables is 
     select object_name, 
     case object_name 
      when 'XP_IMPORT_MW' THEN 99999999 
      when 'XP_IMPORT_MW_ARCH' THEN 99999998 
      else TO_NUMBER(SUBSTR(object_name, -8, 8)) 
     end to_order 
     from dba_objects 
     where object_type = 'TABLE' 
     and object_name IN ('XP_IMPORT_MW', 'XP_IMPORT_MW_ARCH') 
     or REGEXP_LIKE (object_name, 'XP_IMPORT_MW_ARCH_201(5|6|7)[0-9]{4}') order by 2 desc; 

    type t_result is table of xp_import_mw%rowtype; 
    v_result t_result; 

    v_sql varchar2(300); 

BEGIN 
    for i in c_tables 
     loop 
      v_sql := 'select * from ' || i.object_name || ' ' || pi_where; 
      execute immediate v_sql bulk collect into v_result; 

      if v_result.count > 0 
       then 
        for j in v_result.first .. v_result.last 
        loop 
         dbms_output.put_line(v_result(j).art_nr); 
        end loop; 
        dbms_output.put_line('... the required information was found on table name ' || upper(i.object_name)); 
        exit; 
      end if; 
     end loop; 
END prc_checks; 
+0

向我们显示pi_where的值,并假设i.object_name中的任何表具有与xp_import_mv – Typo

+0

相同的行类型。有一个给pi_where的例子:'where col1 = 1' –

回答

2

你会得到这个光标被人发现已较少的列比xp_import_mw中的一个表。例如:

create table xp_import_mw (col1 number, art_nr number, dummy number); 
create table xp_import_mw_arch_20160102 (col1 number, art_nr number, dummy number); 
create table xp_import_mw_arch_20160101 (col1 number, art_nr number); 
insert into xp_import_mw_arch_20160101 values (1, 42); 

所以主xp_import_mw表有三列,但没有匹配的数据。其中一个旧归档表的列数少一个。

我添加了一个dbms_output.put_line(v_sql)的程序,看看它不能针对其表,然后运行它:

set serveroutput on 
exec prc_checks('where col1 = 1'); 

其中有输出:

select * from XP_IMPORT_MW where col1 = 1 
select * from XP_IMPORT_MW_ARCH_20160102 where col1 = 1 
select * from XP_IMPORT_MW_ARCH_20160101 where col1 = 1 

Error starting at line : 49 in command - 
BEGIN prc_checks('where col1 = 1'); END; 
Error report - 
ORA-01007: variable not in select list 
ORA-06512: at "MY_SCHEMA.PRC_CHECKS", line 25 
ORA-06512: at line 1 
01007. 00000 - "variable not in select list" 
*Cause:  
*Action: 

所以问题不在于有没有找到数据;问题是与表中结构错误的数据匹配。

您可以基于xp_import_mw表的结构构建选择列表,而不是使用*;这不会阻止它失败,但至少会给你一个更有帮助的错误信息 - 在这种情况下,ORA-00904: "DUMMY": invalid identifier而不是ORA-01007。

你可以做差异的快速和原油检查的东西,如:

select table_name, count(column_id) as column_count, 
    listagg(column_name, ',') within group (order by column_id) as columns 
from dba_tab_columns 
where table_name IN ('XP_IMPORT_MW', 'XP_IMPORT_MW_ARCH') 
or REGEXP_LIKE (table_name, 'XP_IMPORT_MW_ARCH_201(5|6|7)[0-9]{4}') 
group by table_name 
having count(column_id) != (
    select count(column_id) from dba_tab_columns where table_name = 'XP_IMPORT_MW' 
); 

...但如果你正在使用dba_*all_*视图你确实应该包括所有者,在这里和你程序。

+0

事实上,表结构。我懒惰没有检查每个表中的字段数量,并且存在差异。这些表格有649,651,653列。 – mikcutu

+0

我正在尝试您最后的选择语句,并收到与“ORA-00923:FROM关键字在预期的位置找不到”有关的错误。你有任何线索吗? – mikcutu

+0

我猜你已经在10g(或更早版本)上了,所以listagg不可用......对于650列,结果对于SQL字符串来说太长了。你可以删除它,只需要点数,但你似乎已经知道了数量。 –

相关问题