首页 > 解决方案 > Oracle 存储过程从现有表创建临时表

问题描述

我正在尝试在 oracle 中编写一个存储过程,它应该做一些相对简单的事情:

我希望存储过程采用三个参数,以便可以将其用于表和 where 子句

CREATE OR REPLACE PROCEDURE SYSTEM.COPY_TO_TEMP_TABLE(  
FROM_TABLE IN NCHAR,  
TO_TABLE IN NCHAR,  
WHERE_CLAUSE IN NCHAR  
)  
IS  
BEGIN   
    CREATE TABLE TO_TABLE AS SELECT * FROM FROM_TABLE WHERE WHERE_CLAUSE;  
END COPY_TO_TEMP_TABLE;  

我很难相信过去没有这样做过数千次 - 任何想法为什么这不会为我编译?

标签: oracleprocedure

解决方案


  1. 创建表不是在存储过程中通常会做的事情。与其他一些数据库不同,Oracle 没有本地临时表。如果您必须创建一个临时表,您可以在安装时创建所有其他表时执行此操作。临时表的数据对于插入它的会话是本地的,但定义是跨会话共享的。
  2. 不要在sysorsystem模式中创建对象。这些是为 Oracle 保留的。为要创建的对象创建一个新架构。
  3. nchar如果您正在构建 SQL 语句,则不太可能使用参数。SQL 语句需要使用数据库字符集而不是国家字符集。

如果你想这样做,你需要使用动态 SQL。你可以做类似的事情

create or replace procedure create_table( p_from  in varchar2,
                                          p_to    in varchar2,
                                          p_where in varchar2 )
as
  l_sql varchar2(1000);
begin
  l_sql := ' create table ' || p_to ||
           '  as ' || 
           ' select * from ' || p_from ||
           '  where ' || p_where;
  -- Print it out so you can debug when things inevitably go wrong
  dbms_output.put_line( l_sql );
  execute immediate l_sql;
end;

请注意,这对防止 SQL 注入攻击没有任何作用。我还假设您传入的任何内容都p_where已经正确转义,以便可以将其连接起来(即p_where“foo = ''bar''”而不是“foo = 'bar'”)。您显然可以更改该假设并将转义逻辑添加到过程中。


推荐阅读