动态SQL 表名无效

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态SQL 表名无效相关的知识,希望对你有一定的参考价值。

declare
tbname varchar2(100);
cursor cursor_tbname is
select DISTINCT table_name
from user_tab_columns
where column_name = 'MQ_SENDTIME'
and table_name in (select table_name
from all_all_tables
where table_name like 'O_%'
or table_name like 'I_%'
and owner = 'CYMN');

begin
open cursor_tbname;
loop
fetch cursor_tbname into tbname;
exit when cursor_tbname%notfound;
execute immediate 'delete from table '||tbname|| ' where MQ_SENDTIME < todate( ''2012-12-31'')' ;
end loop;
close cursor_tbname;
END;

提示
ORA-00903: 表名无效
ORA-06512: 在line 18
求解决

参考技术A 加一行,将tbname输出来看一下:

begin
open cursor_tbname;
loop
fetch cursor_tbname into tbname;
exit when cursor_tbname%notfound;

dbms_output.put_line(tbname);

execute immediate 'delete from table '||tbname|| ' where MQ_SENDTIME < todate( ''2012-12-31'')' ;
end loop;
close cursor_tbname;
END;
参考技术B 改为如下:
execute immediate 'delete from '||tbname|| ' where MQ_SENDTIME < todate( ''2012-12-31'')' ;
参考技术C 最好把数据库全名打上

PL/SQL 动态表名

【中文标题】PL/SQL 动态表名【英文标题】:PL/SQL Dynamic Table Names 【发布时间】:2012-08-01 03:47:21 【问题描述】:

我对 Oracle 还很陌生,所以不完全确定这是可能的,或者我可能会以错误的方式进行操作,但这里是...

我正在修复的旧 Feeder 脚本的一部分是循环遍历大约 20 个表(可以随时更改)以填充相关的临时表。这部分目前非常基本:

...

INSERT INTO staging_tbl_1(
     SELECT *
     FROM source_tbl_1    
);

INSERT INTO staging_tbl_2(
         SELECT *
         FROM source_tbl_2    
);

...

源数据库中的某些字段具有不同的约束等,这意味着它会时不时地抛出异常并且馈线将停止。我希望做的是在现有的 feeder 包中创建一个过程,以便在插入之前遍历每条记录中的每一行,并将其简单地包装在一个异常块中。这样就可以在不导致馈线停止的情况下对其进行记录。

基本上我在追求这样的东西:

BEGIN procedure_x(source_record, staging_record)

  -- Perform validation to ensure records exit

  -- Loop through all record rows
  FOR row IN (SELECT * FROM source_record) LOOP

     -- Wrap in exception block

     -- Insert into staging record

     -- Log exception if it occurs
  END LOOP;         
END

我尝试过引用游标,但是为了让它们工作,我还需要提前知道行类型(根据我有限的理解)。我也尝试过立即执行,但是我找不到以适当方式循环它的方法。有没有其他方法可以解决这个问题?

补充:

我意识到我们真的应该解决问题的根源而不是像这样解决问题,不幸的是它远远超出了我的影响范围。

可以在不创建单独过程的情况下执行此操作,只需将所有表引用包装在一个循环中,但是我想将此作为最后的手段。

【问题讨论】:

您是否尝试将EXECUTE IMMEDIATEBULK COLLECT 记录到一个关联数组中,然后您可以循环访问?这可能会解决您的循环问题。 嘿 Ollie,感谢您的回复 - 不幸的是,如果我对批量收集的理解是正确的,我仍然需要在执行之前知道行类型是什么。我目前正在研究 dbms_sql 并创建一个通过 all_tables 等动态创建所有这些的过程。但是,对于这样一个小修复来说,这非常混乱 - 如果有人有其他想法,请告诉我:) 你可以包装一个匿名。在 for 循环中阻止插入语句 - 看看我之前的问题 Continuing Inserts in Oracle when exception is raised 感谢 Sathya 的输入,不幸的是,我认为这不能解决需要事先知道记录名称以创建 for 循环的问题(执行即时问题等)。在这个阶段,看起来 Adam 提到的 DML 错误日志记录可能是我最好的选择。 【参考方案1】:

Oracle 具有记录 DML 错误的功能。将它与单个 SQL 语句一起使用。不要逐行进行,让您的流程爬行。

http://docs.oracle.com/cd/B19306_01/server.102/b14231/tables.htm#ADMIN10261

【讨论】:

谢谢亚当,我想这可能是我必须使用的。不完全是我希望的方式,但正如你所说的那样,它的效率要高得多。

以上是关于动态SQL 表名无效的主要内容,如果未能解决你的问题,请参考以下文章

mysql中查询语句的表名,是不是可以动态选择表名像这样

如何动态替换sql中的表名

Mybatis的动态SQL查询无效

ORA-00903,ORA-06512,同时计算所有用户表的行数(动态 sql)

存储过程的 PL/SQL 动态表名

oracle 动态传入表名,怎么做? 高手指点