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

Oracle 不允许长度为零的列-从视图创建表,oracle,oracle11g,database-administration,Oracle,Oracle11g,Database Administration,我设计了一个将数据从视图复制到oracle中相应表的过程。我所做的就是调用一个过程,将“视图名称”作为参数传递,这将创建相应的表(如果不存在,则删除并创建表)。所以这是动态发生的,我有大约50个视图,它们被安排为oracle作业 现在来讨论这个问题,我有一些表格在某些天出现了以下错误 ORA-01723:不允许使用长度为零的列 我知道这样做的原因是视图中有几列为空,但不是所有的日子都是空的。是的,我应该对这些列使用强制转换,但正如我提到的,这种情况是动态发生的,我不知道这些列是什么,或者是哪个视

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

现在来讨论这个问题,我有一些表格在某些天出现了以下错误

ORA-01723:不允许使用长度为零的列

我知道这样做的原因是视图中有几列为空,但不是所有的日子都是空的。是的,我应该对这些列使用强制转换,但正如我提到的,这种情况是动态发生的,我不知道这些列是什么,或者是哪个视图?在我开始创建表之前,任何用于确定视图中是否存在“零长度列”的线索,以便我可以想出一些解决方案。如果有更好的补救办法,我们将不胜感激

注:

  • 以“从视图中选择*表名-->创建表名”这是我的表创建SQL
  • 我选择此选项的原因是由于日志记录和锁定,“插入”可能需要更多的时间和资源 谢谢,
    Naga'

    正如您所说,您调用一个过程从视图创建一个表。因此,我假设您已经在使用动态SQL(本机动态SQL也称为
    executeimmediate
    语句或
    DBMS\u SQL
    包)来执行DDL语句。然后,您可以使用Oracle字典视图(如和)生成更复杂的
    CREATE TABLE AS
    语句,以获取有关列的类型、长度、比例以及编写右转换调用所需的任何其他信息

    下面是一个肮脏的例子:

    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;
    /
    

    祝您好运。

    正如您所说,您调用了一个过程来从视图创建表。因此,我假设您已经在使用动态SQL(本机动态SQL也称为
    executeimmediate
    语句或
    DBMS\u SQL
    包)来执行DDL语句。然后,您可以使用Oracle字典视图(如和)生成更复杂的
    CREATE TABLE AS
    语句,以获取有关列的类型、长度、比例以及编写右转换调用所需的任何其他信息

    下面是一个肮脏的例子:

    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;
    /
    
    祝你好运

    我选择此选项的原因是由于日志记录和锁定,“插入”可能需要更多的时间和资源

    我认为你每次删除和重新创建表格的方法都是基于错误的信念。截断它们并使用直接路径插入(可选地使用nologging)将在没有此问题的情况下提供几乎相同的结果。如果您正在使用:

    create table .. as select from ...
    
    。。。然后你就可以完全记录操作了

    我选择此选项的原因是由于日志记录和锁定,“插入”可能需要更多的时间和资源

    我认为你每次删除和重新创建表格的方法都是基于错误的信念。截断它们并使用直接路径插入(可选地使用nologging)将在没有此问题的情况下提供几乎相同的结果。如果您正在使用:

    create table .. as select from ...
    

    。。。然后您将完全记录操作。

    为什么不使用物化视图?您对这些表的具体需求是什么?视图只是从单个表中进行的简单筛选选择,还是将函数应用于值?为什么不使用物化视图?您对这些表的具体需求是什么?视图只是从单个表中进行简单筛选选择,还是将函数应用于值?答案很好。我认为使用数据字典是做这件事的正确方法。但示例代码仅适用于基本数据类型,需要对
    timestamp
    等类型进行扩展,并在任何其他情况下复制类型名称。非常感谢。我试过这样的方法,效果很好。。。创建视图虚拟视图,选择1作为id,空作为部门号,从dual中选择“naga”作为名称;创建表dummy\u table as select*from dummy\u view UNION ALL select cast(null as number),cast(null as varchar2(10)),cast(null as varchar2(10))from dual,其中1=2当然,代码必须展开,这只是一个示例来说明这个想法。回答得好。我认为使用数据字典是做这件事的正确方法。但示例代码仅适用于基本数据类型,需要对
    timestamp
    等类型进行扩展,并在任何其他情况下复制类型名称。非常感谢。我试过这样的方法,效果很好。。。创建视图虚拟视图,选择1作为id,空作为部门号,从dual中选择“naga”作为名称;创建表dummy\u table as select*from dummy\u view UNION ALL select cast(null as number)、cast(null as varchar2(10))、cast(null as varchar2(10))from dual,其中1=2当然,代码必须展开,这只是一个示例来说明这个想法。