Oracle 不允许长度为零的列-从视图创建表
我设计了一个将数据从视图复制到oracle中相应表的过程。我所做的就是调用一个过程,将“视图名称”作为参数传递,这将创建相应的表(如果不存在,则删除并创建表)。所以这是动态发生的,我有大约50个视图,它们被安排为oracle作业 现在来讨论这个问题,我有一些表格在某些天出现了以下错误 ORA-01723:不允许使用长度为零的列 我知道这样做的原因是视图中有几列为空,但不是所有的日子都是空的。是的,我应该对这些列使用强制转换,但正如我提到的,这种情况是动态发生的,我不知道这些列是什么,或者是哪个视图?在我开始创建表之前,任何用于确定视图中是否存在“零长度列”的线索,以便我可以想出一些解决方案。如果有更好的补救办法,我们将不胜感激 注:Oracle 不允许长度为零的列-从视图创建表,oracle,oracle11g,database-administration,Oracle,Oracle11g,Database Administration,我设计了一个将数据从视图复制到oracle中相应表的过程。我所做的就是调用一个过程,将“视图名称”作为参数传递,这将创建相应的表(如果不存在,则删除并创建表)。所以这是动态发生的,我有大约50个视图,它们被安排为oracle作业 现在来讨论这个问题,我有一些表格在某些天出现了以下错误 ORA-01723:不允许使用长度为零的列 我知道这样做的原因是视图中有几列为空,但不是所有的日子都是空的。是的,我应该对这些列使用强制转换,但正如我提到的,这种情况是动态发生的,我不知道这些列是什么,或者是哪个视
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当然,代码必须展开,这只是一个示例来说明这个想法。