不允许零长度列 - 从视图创建表

时间:2013-06-05 13:47:23

标签: oracle oracle11g database-administration

我设计了一个将视图中的数据复制到oracle中相应表的过程。我所做的只是调用一个过程,将'view name'作为参数传递,这会创建相应的表(如果不存在,则删除并创建表)。所以这是动态发生的,我有大约50个视图,它们被安排为oracle工作。

现在出现问题我有几张桌子在某些日子里因以下错误而失败......

ORA-01723:不允许零长度列

我知道原因是视图中的几列是null,但并非在所有日子都有。是的我应该为这些列使用CAST,但正如我提到的那样,这是动态发生的我不知道这些列是哪个或哪个是哪个视图?任何导致在我开始创建表之前识别视图中是否存在“零长度列”以便我可以想到一些解决方案。真的很感激任何更好的补救措施。

注意:

  1. 创建表TABLE_NAME AS SELECT * FROM VIEW_NAME - >这是我的表创建SQL。
  2. 我选择此选项的原因是'INSERT INTO'可能因记录和锁定而需要更多时间和资源。
  3. 谢谢, 纳加'

2 个答案:

答案 0 :(得分:1)

正如您所说,您调用过程来从视图创建表。所以我假设您已经在使用动态SQL(Native Dynamic SQL aka EXECUTE IMMEDIATE语句或DBMS_SQL包)来执行DDL语句。然后,您可以使用诸如USER_VIEWSUSER_TAB_COLUMNS之类的Oracle字典视图生成更复杂的CREATE TABLE AS语句,以获取有关列的类型,长度,比例以及您可能需要编写的任何其他内容的信息一个正确的CAST电话。

下面是一个肮脏的例子:

create or replace view v 
as 
  select decode(dummy, 'Y', '123') s 
       , 1 n
       , 2.2 f
       , cast (1.1 as number(5,3)) fs
    from dual
/

set serveroutput on
declare
  l_query varchar2(32767) := 'create table t as select <column list> from v';
  l_type varchar2(100);
begin
  for tc in (
    select * from user_tab_columns 
     where table_name = 'V'
     order by column_id
  ) loop
    l_type := tc.data_type;
    l_type := l_type || 
      case tc.data_type 
        when 'NUMBER' then 
          case when tc.data_precision is not null then '(' || tc.data_precision || case when tc.data_scale is not null then ','||tc.data_scale end || ')' end
        when 'VARCHAR2' then 
          '(' || tc.char_length || ' ' || case tc.char_used when 'C' then 'char' else 'byte' end || ')' 
       end;
    l_query := replace(l_query, '<column list>', 'cast("'||tc.column_name||'" as '|| l_type ||') "'||tc.column_name||'" ,<column list>');
  end loop;
  l_query := replace(l_query, ',<column list>');

  dbms_output.put_line(l_query);
end;
/

结果:

view V created.
anonymous block completed
create table t as select cast("S" as VARCHAR2(3 char)),cast("N" as NUMBER),cast("F" as NUMBER),cast("FS" as NUMBER(5,3)) from v
祝你好运。

答案 1 :(得分:0)

  

我选择这个的原因是'INSERT INTO'可能因记录和锁定而需要更多的时间和资源。

我认为你已经建立了基于错误信念每次丢弃和重新创建表格的方法。截断它们并使用直接路径插入(可选地带有nologging),在没有这个问题的情况下几乎可以得到相同的结果。如果你正在使用:

create table .. as select from ...

...然后你完全记录了这个操作。