ORA-00000: 正常的成功的完成(操作)
ORA-00000: normal, successful completion
原因1: 正常执行完成。
Normal exit.
- 状态: 部分验证。
-
分析: 此异常多数为程序没有执行SQL语句或者说成功执行完SQL语句,但人为或因逻辑有误,非要使用相关方法程序去获取Oracle的错误信息,得到此异常,实质是Oracle告知没有异常产生,猜测是异常信息的默认值为这个。目前发现以下两种情况:
-
存储过程、PL/SQL块等,使用sqlerrm获取异常,如下例所示。【已验证】
declare
v_sqlcode number;
v_sqlerrm varchar2(4000);
begin
/*
……
相关执行代码
……
*/ v_sqlcode := sqlcode;
v_sqlerrm := sqlerrm;
dbms_output.put_line('本次的异常code:' || v_sqlcode || chr(10) || '本次的异常信息:' || v_sqlerrm); exception
when others then
rollback;
v_sqlcode := sqlcode;
v_sqlerrm := sqlerrm;
dbms_output.put_line('本次的异常code:' || v_sqlcode || chr(10) || '本次的异常信息:' || v_sqlerrm);
end;
/ 使用OCI的C程序中,用erhms()函数(OCIErrorGet())获得Oracle错误信息。【未验证,网络汇总】
-
-
措施: 无。【如果是人为需要获取该异常,则不用做任何操作;如果是逻辑有误,那么需要调整不去此异常或者在遇到此异常时将其屏蔽去掉。】
None
原因2: hosts文件配置错误。
- 状态: 未验证,网络汇总。
- 分析: 这种错误通常由于数据库是复制过来的,hosts文件中的ip对应的host name和当前的主机名不一致导致甚至hosts文件丢失,都会导致数据库startup时报此错。
-
措施: 校验hosts文件是否有错或缺失,进行修改或补充。
-
hosts文件在不同系统中所处的目录:
Windows XP/2000/Vista/7/8/8.1/10 ==> C:\windows\system32\drivers\etc\
Linux及其他类Unix操作系统 ==> /etc/
-
ORA-00001: 违反唯一约束条件 (string.string=>[拥有者].[约束名])
ORA-00001: unique constraint (string.string) violated
原因1: UPDATE或INSERT语句试图插入重复的键。对于在DBMS MAC模式下配置的Trusted Oracle,如果在不同级别存在重复条目,您可能会看到此信息。
An UPDATE or INSERT statement attempted to insert a duplicate key. For Trusted Oracle configured in DBMS MAC mode, you may see this message if a duplicate entry exists at a different level.
- 状态: 已验证。
-
分析: 如下例所示,此异常一般为违反作用于表上的唯一约束或者主键约束导致,它们限制了表的一列或多列值的唯一性,不能插入重复数据。
-- 创建测试表
create table ora_00001_1(
a char(24) /*primary key*/, -- 亦可加注释内信息实现添加主键约束
b number /*unique*/, -- 亦可加注释内信息实现添加唯一约束
-- 增加主键约束
constraint ora_00001_1_a primary key (a)
-- 亦可加注释内信息实现添加唯一约束
/*, constraint ora_00001_1_b unique (b)*/
); -- 亦可加注释内信息实现添加主键约束
/*alter table ora_00001_1 add constraint ora_00001_1_a primary key (a);*/
-- 增加唯一约束
alter table ora_00001_1 add constraint ora_00001_1_b unique (b); -- 插入测试数据
insert into ora_00001_1(a, b) values ('1',1);
insert into ora_00001_1(a, b) values ('2',2);
commit; -- ORA-00001: 违反唯一约束条件 (C##LY.ORA_00001_1_A);
insert into ora_00001_1(a, b) values ('1',3);
-- ORA-00001: 违反唯一约束条件 (C##LY.ORA_00001_1_B)
insert into ora_00001_1(a, b) values ('3',2);
-- ORA-00001: 违反唯一约束条件 (C##LY.ORA_00001_1_A)
update ora_00001_1 set a = '1' where a = '2';
-- ORA-00001: 违反唯一约束条件 (C##LY.ORA_00001_1_B)
update ora_00001_1 set b = '2' where b = '1'; -
措施: 删除唯一约束限制或不插入重复值。
Either remove the unique restriction or do not insert the key.
-
如果分析确定此处唯一约束或主键约束不需要,那么则可使用下面语句删除约束
-- 查询约束与索引信息
select a.owner 约束所有者,
a.constraint_name 约束名,
case a.constraint_type
when 'P' then
'Primary key'
when 'U' then
'Unique key'
when 'C' then
' Check constraint on a table'
when 'R' then
'Referential integrity'
when 'V' then
'With check option, on a view'
when 'O' then
'With read only, on a view'
when 'H' then
'Hash expression'
when 'F' then
'Constraint that involves a REF column'
when 'S' then
'Supplemental logging'
else
'unkown'
end 约束类型,
b.table_name 表名,
b.column_name 列名,
c.index_name 索引名,
c.uniqueness 是否唯一索引/*,
d.table_name 表名,
d.column_name 列名*/
from user_constraints a, user_cons_columns b, user_indexes c/*, user_ind_columns d*/
where a.constraint_name = b.constraint_name
and a.index_name = c.index_name
/*and c.index_name = d.index_name*/
and a.owner = b.owner
and a.owner = c.table_owner
and a.owner = &"[拥有者]"
and a.constraint_name = &"[约束名]"; -- 由于如果约束对应的唯一索引若是事先手工创建的,那么在删除约束时索引不会被删除,Oracle之后自动删除自己隐式创建的索引。
-- 因此加上drop index,可确保一定将索引删除。
alter table [表名] drop constraint [约束名] drop index;
-- 如果是主键约束,有可能遇到有用作外键的情况,那么在删除时仍会报=>ORA-02273: 此唯一/主键已被某些外键引用
-- 报错后了解是否有问题,是否需去除此主键和外键,然后可考虑用下面语句删除主键约束,会同时删除外键约束
alter table [表名] drop constraint [约束名] cascade drop index;
alter table [表名] drop primary key cascade drop index; 如果分析确定是值重复,那么需排查表数据与预执行的SQL语句的重复值冲突、同一个事务内执行的SQL语句之间的重复值冲突,去掉重复值的插入或更新。
-
- 备注:
- 唯一约束与主键约束的同:
- 都通过唯一索引来限制约束列的唯一性,确保任何使表中约束的列在行与行之间存在重复值的操作失败
- 若无事先创建好唯一索引,都会在创建唯一约束或主键约束时隐式创建同名的唯一约束
- 有约束必定有索引(无法在保持约束存在的情况下删除索引=>ORA-02429: 无法删除用于强制唯一/主键的索引)
- 有索引不一定有约束(只删除约束但不删除索引则仍然会限制索引列的值的唯一性)
- 唯一约束与主键约束的异:
- 唯一约束允许在该列或多列上存在NULL值,但主键约束不能存在NULL值
- 一个表只能创建一个主键约束,但可创建多个唯一约束
- 主键可扩展作为外键,唯一约束不可
- 唯一约束与主键约束的同:
ORA-00017: 会话被要求设置跟踪事件
ORA-00017: session requested to set trace event
原因1: 当前会话被要求通过另一个会话设置一个跟踪事件
The current session was requested to set a trace event by another session.
- 状态: 来源ORA12_ERRMG。
-
措施: 内部使用;无需操作。
This is used internally; no action is required.
ORA-00018: 超出最大会话数
ORA-00018: maximum number of sessions exceeded
原因1: 所有会话状态对象都在使用中
All session state objects are in use.
- 状态: 部分验证。
- 分析: 很明显,系统中所有会话数目已经达到设置的SESSIONS值,因此准备要创建的会话无法成功创建,而这个会话包括有用户建立连接至数据库是产生的会话、后台进程产生的会话以及各类涉及到硬解析处理数据字典基表的DML、DDL语句产生的递归会话。
-
措施: 增加SESSIONS初始化参数值。【是否需要增加SESSIONS值还需进行判断,是否是由于此值过小而现实场景需要更大的值?】
Increase the value of the SESSIONS initialization parameter.
-
如果判断确定是由于SESSIONS值过小导致,则需修改增大此参数值【已验证】:
alter system set 参数名=参数值 [comment='注释'] [deferred] [scope=memory|spfile|both] [sid='sid|*'];
/*
comment='注释',修改时可添加注释,会在V$PARAMETER视图的update_comment字段看到内容,和参数值生效情况保存一致;
deferred,指定参数修改是否只对以后的会话生效(对当前建立的会话无效,包括执行此修改的会话),部分参数必须加此参数;
scope=both,表示修改会立即生效且会修改spfile文件以确保数据库在重启后也会生效如果(以spfile启动此项为缺省值);
scope=memory,表示修改会立即生效但不会修改spfile文件,因此重启后失效(以pfile启动此项为缺省值,且只可设置这个值);
scope=spfile,表示只修改spfile文件,在重启实例后才生效(以spfile启动且为静态参数则必须设置此项值);
sid='sid|*',默认是sid=*,可改为在集群环境中的一个指定的实例值。
*/ -- 查看"ALTER SYSTEM修改模式"列值,根据结果进行修改
select name 参数名,
case type
when 1 then
'Boolean'
when 2 then
'String'
when 3 then
'Integer'
when 4 then
'Parameter file'
when 5 then
'Reserved'
when 6 then
'Big integer'
else
'unknown'
end 参数类型,
value "会话级(若可修改)或实例级参数值",
display_value 展示值,
isses_modifiable "是否可用ALTER SESSION修改",
case issys_modifiable
when 'IMMEDIATE' then
'无论pfile还是spfile启动,都可用"alter system set ' || name || '=&' ||
'新的参数值;"更改参数并立即生效。'
when 'DEFERRED' then
'无论pfile还是spfile启动,都要用"alter system set ' || name || '=&' ||
'新的参数值 deferred;"更改参数并将在之后的会话中生效。'
when 'FALSE' then
case a.is_spfile
when 0 then
'使用pfile启动,需手动修改pfile文件中对应参数值再重启。'
else
'使用spfile启动,可用"alter system set ' || name || '=&' || name ||
' scope=spfile;"更改参数。更改将在后续的实例中生效(当前数据库需重启)。'
end
else
'?'
end "ALTER SYSTEM修改模式",
isinstance_modifiable "是否不同实例间值可不同"
from v$parameter,
(select count(1) is_spfile from v$parameter t where t.name = 'spfile' and t.value is not null) a
where name = 'sessions'; 如果判断确定SESSIONS值合理,则需分析确定产生大量会话的原因,是否相关程序代码建立了连接未释放?或者其它原因等。【待完善】
-
备注: 参数SESSIONS:
属性 | 描述 |
---|---|
参数类型 | Integer |
默认值 | 派生公式: 【?~11gR1】="(1.1 * PROCESSES) + 5)"; 【11gR2~12cR2】="(1.5 * PROCESSES) + 22" |
可修改(不用重启及时生效) | 【?~11gR2】="否"; 【12cR1~12cR2】="可用ALTER SYSTEM修改" |
取值范围 | 【?~11gR1】="1~2^31"; 【11gR2~12cR2】="1~2^16(即1~65536)" |
基础参数 | 是 |
SESSIONS指定可以在系统中创建的最大会话数。因为每次登录都需要一个会话,所以这个参数有效地确定了系统中最大并发用户数。您应该始终将此参数显式设置等于最大并发用户数的估计值+后台进程数+递归会话数(大约占总数的10%)。
Oracle使用此参数的默认值作为其最小值。 将SESSIONS值设置成[1~默认值)不会触发错误,因为Oracle会忽略此值直接使用默认值。
ENQUEUE_RESOURCES和TRANSACTIONS参数的默认值派生自SESSIONS。因此,如果增加SESSIONS的值,则应考虑是否也调整ENQUEUE_RESOURCES和TRANSACTIONS的值。 (请注意,从Oracle Database 10g release 2(10.2)起,ENQUEUE_RESOURCES已被废弃。)
在共享服务器环境中,PROCESSES的值可能相当小。因此,Oracle建议您将SESSIONS的值调整为大约1.1 *总连接数。
ORA-00019: 超出最大许可会话数
ORA-00019: maximum number of session licenses exceeded
原因1: 所有许可会话都在使用中。
All licenses are in use.
- 状态: 部分验证。
- 分析: 很明显,系统中并发用户会话已经达到设置的LICENSE_MAX_SESSIONS值,因此准备要创建的用户会话无法创建。
-
措施: 增大LICENSE_MAX_SESSIONS初始化参数的值。【是否需要增加LICENSE_MAX_SESSIONS值还需进行判断,是否是由于此值过小而现实场景需要更大的值?】
Increase the value of the LICENSE MAX SESSIONS initialization parameter.
- 如果判断确定是由于LICENSE_MAX_SESSIONS值过小导致,则需修改增大此参数值,【详情参见ORA-00018=>原因1=>措施,将SQL语句中
name = 'sessions'
修改为name = 'license_max_sessions'
即可】 - 如果判断确定LICENSE_MAX_SESSIONS值合理,则需分析确定产生大量会话的原因,是否相关程序代码建立了连接未释放?或者其它原因等。【待完善】
- 如果判断确定是由于LICENSE_MAX_SESSIONS值过小导致,则需修改增大此参数值,【详情参见ORA-00018=>原因1=>措施,将SQL语句中
备注: 参数LICENSE_MAX_SESSIONS:
属性 | 描述 |
---|---|
参数类型 | Integer |
默认值 | 0 |
可修改(不用重启及时生效) | 可用ALTER SYSTEM修改 |
取值范围 | 0~许可会话数 |
基础参数 | 否 |
Oracle实时应用集群 | 多个实例可以具有不同的值,但是安装数据库的所有实例的总和应小于或等于该数据库许可的会话总数。 |
LICENSE_MAX_SESSIONS指定允许的并发用户会话的最大数量。达到此限制后,只有具有RESTRICTED SESSION权限的用户才能连接到数据库。无法连接的用户收到表示系统达到最大容量的警告消息。
零值表示不强制执行并发使用(会话)许可。如果将此参数设置为非零数字,则可能还需要设置LICENSE_SESSIONS_WARNING(请参阅“LICENSE_SESSIONS_WARNING”)。
不要同时启用并发使用许可和用户许可,即LICENSE_MAX_SESSIONS与LICENSE_MAX_USERS两参数值至少一个要设置为零。
ORA-00020: 超出最大进程数(string=>[最大进程数])
ORA-00020: maximum number of processes (string) exceeded
原因1: 所有进程状态对象都在使用中。
All process state objects are in use.
- 状态: 部分验证。
- 分析: 很明显,系统中进程数已经达到设置的PROCESSES值,因此准备要创建的用户会话无法创建。
-
措施: 增加PROCESSES初始化参数的值。【是否需要增加PROCESSES值还需进行判断,是否是由于此值过小而现实场景需要更大的值?】
Increase the value of the PROCESSES initialization parameter.
- 如果判断确定是由于PROCESSES值过小导致,则需修改增大此参数值,【详情参见ORA-00018=>原因1=>措施,将SQL语句中
name = 'sessions'
修改为name = 'processes'
即可】 - 如果判断确定PROCESSES值合理,则需分析确定产生大量进程的原因,是否相关程序代码建立了连接未释放?或者其它原因等。【待完善】
- 如果判断确定是由于PROCESSES值过小导致,则需修改增大此参数值,【详情参见ORA-00018=>原因1=>措施,将SQL语句中
备注: 参数PROCESSES:
属性 | 描述 |
---|---|
参数类型 | Integer |
默认值 | 【?~10gR2】="40~操作系统依赖数"; 【11gR1~11gR2】="100"; 【12cR1~12cR2】="该值是派生的,它通常取决于警报日志中报告的核心数。" |
可修改(不用重启及时生效) | 否 |
取值范围 | 6~操作系统依赖数 |
基础参数 | 是 |
Oracle实时应用集群 | 多个实例可以具有不同的值。 |
PROCESSES指定可以同时连接到Oracle的最大操作系统用户进程数。它的值应允许所有后台进程运行,如锁,作业队列进程和并行执行进程。
该参数派生了SESSIONS和TRANSACTIONS参数的默认值。因此,如果更改PROCESSES的值,则应评估是否要调整这些派生参数的值。
ORA-00439: 未启用功能: 【功能名】
ORA-00439: feature not enabled: string
原因1: 指定的功能未启用。
The specified feature is not enabled.
- 状态: 已验证。
- 分析: ORACLE:你要多给我点钱,知道不!
-
措施: 不要尝试使用此功能。
Do not attempt to use this feature.
- 哎,哥们,实在想用此项功能,那就换高版本换企业版之类有这个功能的数据库吧。
- 如果是别人库导过来的,嗯,它的库鄙视了下你的库,擦把汗告诉别人导出时指定下低版本。
ORA-01502: 索引 '(SCHEMA名).(索引名)' 或这类索引的分区处于不可用状态
ORA-01502: index 'string.string' or partition of such index is in unusable state
原因1: 试图连接访问被"直接负载?"或DDL语句操作标记为不可用状态的索引或索引的分区
An attempt has been made to access an index or index partition that has been marked unusable by a direct load or by a DDL operation
- 状态: 已验证。
-
分析: 一般是因为在执行DML语句操作表数据时,表上用到了主键约束、唯一约束需要用到索引的或者是表上单独设置了唯一索引的或者是其它情况需要处理到索引或索引分区的,而此时索引或索引分区却是被标记为不可用状态,导致想执行的操作无法执行而报错。如下例所示:
-- 创建表与主键
create table ora_01502_1(a number, b varchar2(30));
alter table ora_01502_1 add constraints pk_ora_01502_1_a primary key(a);
-- 标记索引UNUSABLE
alter index pk_ora_01502_1_a unusable;
-- 执行插入语句报错
insert into ora_01502_1 (a,b) values(1,'1');
-- 查看索引、约束状态。索引不可用,约束生效
select t.status, t.* from user_indexes t where t.table_name = 'ORA_01502_1';
select t.status, t.* from user_constraints t where t.table_name = 'ORA_01502_1'; -- 创建表与唯一索引
create table ora_01502_2(a number, b varchar2(30));
create unique index pk_ora_01502_2_a on ora_01502_2(a);
-- 标记索引UNUSABLE
alter index pk_ora_01502_2_a unusable;
-- 执行插入语句报错
insert into ora_01502_2 (a,b) values(1,'1');
-- 查看索引状态。索引不可用
select t.status, t.* from user_indexes t where t.table_name = 'ORA_01502_1'; -
措施: DROP指定的索引,或REBUILD指定的索引,或REBUILD不可用的索引分区
DROP the specified index, or REBUILD the specified index, or REBUILD the unusable index partition
- 如果需要修复索引或索引分区,通过rebuild进行重建。
- 如果需要去掉索引,通过drop命名删除,如果有约束得先删除约束(如果是创建约束时系统自动创建的索引会在删除约束时一起删除),然后再删除索引(如果是创建约束前手工建立的索引,那么还需要手工维护进行删除)
ORA-01722: 无效数字
ORA-01722: invalid number
原因1: 指定的数字无效
The specified number was invalid.
- 状态: 已验证。
-
分析: 究其根本在于,要执行的语句在人为显式转换或Oracle判断决定隐式转换,故意或非故意得使一个非数值类型且无法转换为数值类型的值转换为数值类型失败导致的。如下几例:
-
显式转换:
-- to_number、to_binary_float、to_binary_double转换字符串为数值
select to_number('2017年') from dual;
select to_binary_float('8.935M') from dual;
select to_binary_double('0.001s') from dual; -
隐式转换:
---------涉及到数值类型列的赋值或函数需要函数数值类型结果的转换---------
-- insert/update/merge等语句操作列值
-- 测试表
create table ora_01722_1(
a number,
b char(24),
c varchar2(300)
);
-- 插入赋值,无法隐式转换成数值,报错
insert into ora_01722_1(a) values ('111测试字符串');
-- 插入赋值,可以隐式转换成数值,不报错
insert into ora_01722_1(a, b) values ('111', 'bbb');
commit;
-- 更新赋值,无法隐式转换成数值,报错
update ora_01722_1 set a = '222测试字符串'; -- decode由第三列的数值1确定了该函数输出结果为数值类型
-- 当匹配到'a'返回1,结果为数值,不报错
select decode('a', 'a', 1, 'b', 2, 'c', 'three', 0) test1 from dual;
-- 当匹配到'c'返回'three',结果不为数值且无法转换为数值,报错
select decode('c', 'a', 1, 'b', 2, 'c', 'three', 0) test2 from dual; -- nvl由第一列输入的数值确定了它在此时输出的结果也会为数值类型
-- 当发现第一个值不为空时,就尝试输出后边的值作为本次nvl函数操作后的数值结果,发现无法转换为数值,报错
select nvl(&请输入数值, '测试') from dual; -- nvl2由第二列的2确定了它在此时输出的结果也会为数值
-- 当不管结果是否为2,它都会讲后边的值进行测试转换……所以无论是否输入null都报错
select nvl2(&无论是否null, 2, '测试') from dual; ---------涉及到与数值类型的比较或其它运算---------
-- 未比较到'三',不报错
select decode(1, 1, 'one', 2, 'two', '三', 'three', 'zero') from dual;
-- 比较到'三',报错
select decode(3, 1, 'one', 2, 'two', '三', 'three', 'zero') from dual;
-- 与数值进行算术运算,无法隐式转换为数值,报错
select 'a' + 2 from dual;
-- 与ora_01722_1的数值类型列a进行比较,将右边转换为数值失败,报错
select * from ora_01722_1 t where t.a = 'a';
-- ora_01722_1列b与数值类型进行比较,将左边转换为数值失败,报错
select * from ora_01722_1 t where t.b = 2;特别注意时灵时不灵的查询,基本都类似于下面的情况,灵的时候是因为之前查询的是部分表数据或部分视图数据等,不灵的时候则是涉及到另一部分甚至是全表全视图的数据,而由于未注意隐式转换导致其中“脏数据”无法转换成数值类型而报错。根源不是数据脏,是使用者不注意字段类型的区分,所以我们不要依赖于Oracle的隐式转换!
-
-
措施: 指定一个有效的数字。
Specify a valid number.
- 根据分析的情况,明确是否需要主动转换,是否数据存在问题,该是数值就传数值,该是字符串就添加左右英文单引号包裹成字符串。
-
备注: 当需要的时候,Oracle数据库会自动将值从一种数据类型转换为另一种(如CHAR、VARCHAR2、NCHAR、NVARCHAR2、BINARY_FLOAT、BINARY_DOUBLE就有可能隐式转换为NUMBER)。由于以下原因,Oracle建议您指定显式转换,而不是依赖于隐式自动转换:
- 当您使用显式数据类型转换函数时,SQL语句更容易理解。
- 隐式数据类型转换可能会对性能产生负面影响,特别是如果列值的数据类型被隐式转换为基本常量的数据类型,而不是主动转为其它类型。
- 隐式转换要根据需要转换时的上下文来决定,而且在每类场景中不一定产生一样的效果。例如,从datetime值到varchar2值的隐式转换可能会根据NLS_DATE_FORMAT参数的值返回意外的一年。
- 隐式转换的算法可能会随着软件版本和Oracle产品之间的变化而变化。显式转换的变化则更有预见性。
- 如果在索引表达式中产生了隐式数据类型转换,那么Oracle数据库可能不会使用该索引,因为它是为转换前数据类型定义的。这可能会对性能产生负面影响。
ORA-01747: 用户.表.列、表.列或列格式无效
ORA-01747: invalid user.table.column, table.column, or column specification
原因1: 列名为关键字。
- 状态: 已验证。
-
分析: 一般为在SQL语句或存储过程、函数等中使用到的此字段为oracle的保留关键字,且保留方式标识了此关键字在某些情况下,例如在DML中是否不允许作为标识符的。如下列情况:
-- 查询能做属性但不能作为标识符或某些场景(如DML操作)下不能作为标识符的关键字
select t.*
from v$reserved_words t
where (t.res_semi = 'Y' or t.reserved = 'Y')
and t.res_attr = 'N';
-- 根据上面关键字建表,为测试需要,实际使用时请避免将Oracle保留关键字作为表的字段!
create table ora_01747_1 (
"TRIGGER" number, "WHERE" number, "REVOKE" number, "INCREMENT" number, "THEN" number,
"FILE" number, "PRIOR" number, "CONNECT" number, "COMMENT" number, "SYSDATE" number,
"ONLINE" number, "DECIMAL" number, "SESSION" number, "MODIFY" number, "IN" number,
"@" number, "," number, "GRANT" number, "INTO" number, "VALIDATE" number, "." number,
"ADD" number, "ORDER" number, "HAVING" number, "TO" number, "NULL" number, "RENAME" number,
"LEVEL" number, "USER" number, "ANY" number, /*"ROWID" number, --不可作建表属性*/
"SHARE" number, "MODE" number, "UNION" number, "/" number, "SET" number, "INDEX" number,
"MAXEXTENTS" number, "VALUES" number, "|" number, "VIEW" number, "[" number, "WITH" number,
"EXCLUSIVE" number, "ALTER" number, "FROM" number, "SELECT" number, "BY" number, "-" number,
"MLSLABEL" number, "AND" number, "+" number, "ROWS" number, "CHECK" number, ":" number,
"VARCHAR2" number, "IMMEDIATE" number, "CURRENT" number, "AS" number, "*" number, "TABLE" number,
"LONG" number, "SYNONYM" number, "ASC" number, "UNIQUE" number, "LIKE" number, "DESC" number,
"VARCHAR" number, "INITIAL" number, "CHAR" number, "=" number, "DROP" number, "AUDIT" number,
"ROWNUM" number, "FLOAT" number, "COMPRESS" number, "OFFLINE" number, "NOT" number, "DELETE" number,
"^" number, "BETWEEN" number, "EXISTS" number, "IDENTIFIED" number, "WHENEVER" number, "INTEGER" number,
"SIZE" number, "NOWAIT" number, ")" number, "]" number, "NOCOMPRESS" number, "COLUMN" number, "ELSE" number,
"FOR" number, "INTERSECT" number, "!" number, "PRIVILEGES" number, "SUCCESSFUL" number, "PCTFREE" number,
"UPDATE" number, "ACCESS" number, "RESOURCE" number, "UID" number, "DATE" number, "NOAUDIT" number,
"RAW" number, /*"&" number,--不可作建表属性 */"OPTION" number, "ROW" number, "SMALLINT" number,
"MINUS" number, "OF" number, "ON" number, ">" number, "INSERT" number, "DEFAULT" number, "ALL" number,
"START" number, "IS" number, "CREATE" number, "DISTINCT" number, "LOCK" number, "CLUSTER" number,
"GROUP" number, "PUBLIC" number, "OR" number, "<" number, "NUMBER" number, "(" number/* ,"" number --不可作建表属性*/
); -- 异常测试(不是所有属性错误使用都会产生ORA-01747的异常,还可能产生ORA-00936、ORA-01788、ORA-01745等异常)
-- ORA-01747: user.table.column, table.column 或列说明无效
select SET from ora_01747_1;
update ora_01747_1 set NUMBER = 1;
update ora_01747_1 set ,"NUMBER" = 1;
insert into ora_01747_1("TRIGGER", ,WHERE) values(1, ,1); -
措施: 在使用此字段时,添加英文双引号("")包裹。
-
通过下面语句可查询此类关键字的使用情况:
select a.table_name 表,
a.column_name 原字段,
'"' || a.column_name || '"' 使用需加双引号,
'select "' || a.column_name || '" from ' || a.table_name ||
' where rownum = 1;' 简单查询语句,
b.reserved "是否不能作标识符",
b.res_type "是否不能作类型名称",
b.res_attr "是否不能作属性名称",
b.res_semi "是否某些环境(DML)不能作标识符",
b.duplicate
from user_tab_columns a, v$reserved_words b
where a.column_name = b.keyword
and b.res_semi = 'Y'
-- and a.table_name = '表名'
-- and a.column_name = '字段名'
;
-
备注: 实际使用时请避免将Oracle保留关键字作为表的字段!
原因2: DML语句缺失列或多逗号。
- 状态: 已验证。
- 分析: 一般为使用各种方式动态拼接SQL时,拼接有误,使得insert语句或update语句中逗号分隔的左边或右边出现空,示例可参见上面原因1的分析代码。
- 措施: 检查拼接逻辑,加上缺失字段或去除多余的逗号
ORA-02095: 无法修改指定的初始化参数
specified initialization parameter cannot be modified
原因1: 指定的初始化参数不可修改
The specified initialization parameter is not modifiable
- 状态: 已验证。
- 分析: 无法使用
alter system set 参数名=参数值;
修改初始化参数,一般是当前实例是以pfile启动时,修改参数时出现此情况(当scope=spfile会提示ORA-32001错误);或者是以spfile启动时,对静态参数未用scope=spfile选项进行修改时出现此情况。 -
措施: 不可用
N/A
- 实际上可通过
select value from v$parameter t where t.name = 'spfile';
或SQL*Plusshow parameter spfile;
进行查询,如果有值(spfile的文件位置)代表以spfile启动,则可通过alter system set 参数值=参数名 scope=spfile;
来修改;如果是没值,以pfile启动,则必须找到pfile文件打开进行手动编辑修改对应参数值。最终都得重启实例才可生效。
- 实际上可通过
-
备注:
-
PFILE启动init.ora参数文件默认位置:
$ORACLE_HOME/dbs/init$ORACLE_SID.ora (Unix)
%ORACLE_HOME%\database\init%ORACLE_SID%.ora (Windows)
-
ORA-02096: 指定的初始化参数不能使用此选项进行修改
ORA-02096: specified initialization parameter is not modifiable with this option
原因1: 虽然初始化参数是可修改的,但不能使用指定的命令进行修改。
Though the initialization parameter is modifiable, it cannot be modified using the specified command.
- 状态: 已验证。
-
分析: 数据库启动的初始化参数根据启动参数文件pfile和spfile的不同,以及参数的本身要求的不同,在使用
alter system set 参数名=参数值;
时需要加不同的scope值、deferred限制应用范围。如果这些配置选项选择错误,则会导致无法修改。暂只发现需加deferred配置选项进行修改的参数未加时,报此错,如下例所示:-- 报错,必须加deferred配置选项
alter system set object_cache_max_size_percent=&新的参数值; -
措施: 检查DBA指南,了解有关参数可能被修改的范围的信息
Check the DBA guide for information about under what scope the parameter may be modified
-
一般是加上deferred选项即可,可用下面语句查看具体情况
alter system set 参数名=参数值 [comment='注释'] [deferred] [scope=memory|spfile|both] [sid='sid|*'];
/*
comment='注释',修改时可添加注释,会在V$PARAMETER视图的update_comment字段看到内容,和参数值生效情况保存一致;
deferred,指定参数修改是否只对以后的会话生效(对当前建立的会话无效,包括执行此修改的会话),部分参数必须加此参数;
scope=both,表示修改会立即生效且会修改spfile文件以确保数据库在重启后也会生效如果(以spfile启动此项为缺省值);
scope=memory,表示修改会立即生效但不会修改spfile文件,因此重启后失效(以pfile启动此项为缺省值,且只可设置这个值);
scope=spfile,表示只修改spfile文件,在重启实例后才生效(以spfile启动且为静态参数则必须设置此项值);
sid='sid|*',默认是sid=*,可改为在集群环境中的一个指定的实例值。
*/ -- 查看"ALTER SYSTEM修改模式"列值,根据结果进行修改
select name 参数名,
case type
when 1 then
'Boolean'
when 2 then
'String'
when 3 then
'Integer'
when 4 then
'Parameter file'
when 5 then
'Reserved'
when 6 then
'Big integer'
else
'unknown'
end 参数类型,
value "会话级(若可修改)或实例级参数值",
display_value 展示值,
isses_modifiable "是否可用ALTER SESSION修改",
case issys_modifiable
when 'IMMEDIATE' then
'无论pfile还是spfile启动,都可用"alter system set ' || name || '=&' ||
'新的参数值;"更改参数并立即生效。'
when 'DEFERRED' then
'无论pfile还是spfile启动,都要用"alter system set ' || name || '=&' ||
'新的参数值 deferred;"更改参数并将在之后的会话中生效。'
when 'FALSE' then
case a.is_spfile
when 0 then
'使用pfile启动,需手动修改pfile文件中对应参数值再重启。'
else
'使用spfile启动,可用"alter system set ' || name || '=&' || name ||
' scope=spfile;"更改参数。更改将在后续的实例中生效(当前数据库需重启)。'
end
else
'?'
end "ALTER SYSTEM修改模式",
isinstance_modifiable "是否不同实例间值可不同"
from v$parameter,
(select count(1) is_spfile from v$parameter t where t.name = 'spfile' and t.value is not null) a
where name = &参数名小写;
-
ORA-02437: 无法验证 (【SCHEMA名】.【主键名】) - 违反主键
ORA-02437: cannot validate (string.string) - primary key violated
原因1: 尝试使用重复值或空值验证主键。
attempted to validate a primary key with duplicate values or null values.
- 状态: 已验证。
-
分析: 创建主键约束时启用对已有数据的校验,或创建主键约束时禁用对已有数据的校验但约束对应的索引是唯一索引仍进行了校验。校验时表中约束列存在重复值或者空值(空值有疑虑,测试发现先校验空值报ORA-01449: 列包含 NULL 值; 无法将其变更为 NOT NULL),以致无法创建主键而报错,如下例所示:
-- 创建表与主键
create table ora_02437_1(a number, b varchar2(30));
-- 插入重复数据
insert into ora_02437_1(a,b) values(1,'1');
insert into ora_02437_1(a,b) values(1,'1');
-- 创建主键报错
alter table ora_02437_1 add constraints pk_ora_02437_1_a primary key(a)
--(enable) (validate) -- 默认enable启用约束,且默认validate对已有数据进行校验
;
-- 创建主键限制不对已有数据进行校验,仍然报错
alter table ora_02437_1 add constraints pk_ora_02437_1_a primary key(a) enable novalidate ;
-- 查看没有索引,但约束使用须有索引,而在创建唯一约束时系统默认给创建唯一索引,所以上条语句会报错
select t.status, t.* from user_indexes t where t.table_name = 'ORA_02437_1'; -
措施: 在启用主键之前,请删除重复项和空值。
remove the duplicates and null values before enabling a primary key.
- 如果需要对已有数据进行校验并添加主键,则需查询表并清除重复项和空值,而后再创建主键约束。
-
如果不需要对已有数据进行校验,则需先创建普通索引,再创建主键约束且加novalidate限制。
-- 先创建索引
create index pk_ora_02437_1_a on ora_02437_1(a)
-- online --可同时加online参数保证创建索引的时候不阻塞DML操作,以免对运行中的系统造成影响
;
-- 再创建主键
alter table ora_02437_1 add constraints pk_ora_02437_1_a primary key(a) novalidate ;
-- 清除重复项和空值后可再启动对已有数据校验
alter table ora_02437_1 modify constraint pk_ora_02437_1_a validate;
ORA-14048: 分区维护操作不能与其他操作组合
ORA-14048: a partition maintenance operation may not be combined with other operations
原因1: ALTER TABLE或ALTER INDEX语句试图将分区维护操作(例如MOVE PARTITION)与某些其他非法的操作(例如ADD PARTITION或PCTFREE)组合
ALTER TABLE or ALTER INDEX statement attempted to combine a partition maintenance operation (e.g. MOVE PARTITION) with some other operation (e.g. ADD PARTITION or PCTFREE which is illegal
- 状态: 部分验证,暂时只遇到下面分析中的例子。
-
分析: ALTER TABLE或ALTER INDEX语句的参数之前有冲突,其它操作对分区维护的操作造成影响。有可能是人为执行设置的语句;亦有可能类似于下例情况,oracle拼接而成的语句:
-- 创建测试表,在字段后加primary key,则是系统自动生成的约束和索引的名称,而不是人为指定。
create table ora_14048(a number primary key, b varchar2(30));
-- 将测试表主键约束对应的索引设置为不可用状态
alter index SYS_C009537 unusable; -- windows系统cmd窗口导出测试表
expdp C##LY/密码@XE tables=ora_14048 dumpfile=ora_14048.dmp directory=data_pump_dir logfile=expdp_ora_14048.log
-- 然后导入测试表
impdp INFA/密码@XE remap_schema=C##LY:INFA dumpfile=ora_14048.dmp directory=data_pump_dir logfile=impdp_ora_14048.log
-- 导入有错,日志如下
;;;
Import: Release 11.2.0.2.0 - Production on 星期五 9月 1 10:43:59 2017 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
;;;
连接到: Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
已成功加载/卸载了主表 "INFA"."SYS_IMPORT_FULL_01"
启动 "INFA"."SYS_IMPORT_FULL_01": INFA/********@XE remap_schema=C##LY:INFA dumpfile=ora_14048.dmp directory=data_pump_dir logfile=impdp_ora_14048.log
处理对象类型 TABLE_EXPORT/TABLE/TABLE
处理对象类型 TABLE_EXPORT/TABLE/TABLE_DATA
. . 导入了 "INFA"."ORA_14048" 0 KB 0 行
处理对象类型 TABLE_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
ORA-39083: 对象类型 CONSTRAINT 创建失败, 出现错误:
ORA-14048: 分区维护操作不能与其他操作组合
失败的 sql 为:
ALTER INDEX "INFA"."SYS_C009537" UNUSABLE ENABLE
作业 "INFA"."SYS_IMPORT_FULL_01" 已经完成, 但是有 1 个错误 (于 10:44:01 完成) -- 查询该表索引和约束情况,发现状态还是正常,索引约束都建立起来了。只是索引名约束名不一致,且索引未能与来源库中一样状态为UNUSABLE。
select t.status, t.* from user_indexes t where t.table_name = 'ORA_14048';
select t.status, t.* from user_constraints t where t.table_name = 'ORA_14048'; -
措施: 确保分区维护操作是ALTER TABLE或ALTER INDEX语句中指定的唯一操作;除处理分区之外的,分区表/索引的默认属性的操作或指定表重命名(ALTER TABLE RENAME)的操作都可以随意组合
Ensure that a partition maintenance operation is the sole operation specified in ALTER TABLE or ALTER INDEX statement; operations other than those dealing with partitions, default attributes of partitioned tables/indices or specifying that a table be renamed (ALTER TABLE RENAME) may be combined at will
- 人为执行设置的语句,那么还是主动拆开执行操作。
- 如果是分析中提到的例子,那么猜测是由于oracle的程序内部的问题,未能正常拼接好执行语句,所以如果仍需要将该索引设置为不可用状态,那么在目标库里面同样执行一下设置语句即可(注意,由于是系统生成的索引名,那么在导入到目标库时也是由目标库自主生成的索引名,因此会出现索引名称不一致。需要查询表在目标库里真正的索引名称,然后进行操作);如果不需要设置为不可用状态,那么久不用执行:
-- 但由于索引名称不一致的问题,如果是导入的表空间或用户等更大级别的数据,那么出现问题时估计就不清楚需要设置不可用状态的索引具体对应的是哪个表了
-- 此时估计应该从来源库中查询到对应索引的所在表,然后再在目标库中找到该表的索引获取到索引名称然后进行操作。
alter index SYS_C009554 unusable;
ORA-14063: 唯一/主键约束条件关键字中存在无用索引
ORA-14063: Unusable index exists on unique/primary constraint key
原因1: 用户尝试添加或启用主键/唯一约束于(多)列,但这些列上的索引存在有标记为Index Unusable的。
User attempted to add or enable a primary key/unique constraint on column(s) of a table on which there exists an index marked Index Unusable.
- 状态: 已验证。
- 分析: 约束要想有效,都必须通过索引来实现,创建约束时都会默认创建同名的索引或关联到约束字段上已有的索引。索引通过
alter index 索引名 unusable;
可设置为不可用状态,那么关联的约束就无法正常启用或者想在索引限制的字段上创建约束也是无法创建成功的。 -
措施: 删除现有索引或使用ALTER INDEX REBUILD重建它。
Drop the existing index or rebuild it using ALTER INDEX REBUILD
- 如果判断确定,仍需要创建或启用主键约束或唯一约束,那么则需执行
alter index 索引名 rebuild;
将索引重建或者先删除该索引,然后再执行对应约束语句即可。 - 如果判断确定,此处不需要再创建或启用约束,那么就不用管,让这个索引继续保持UNUSABLE,并保持对未来同样的操作的抗拒状态:);或者将索引删除,那么以后有其他人想创建就不会再遇到这个问题了。
- 如果判断确定,仍需要创建或启用主键约束或唯一约束,那么则需执行
ORA-32001: 已请求写入 SPFILE, 但是没有正在使用的 SPFILE
ORA-32001: write to SPFILE requested but no SPFILE is in use
原因1: ALTER SYSTEM命令或内部自调整机制请求写入SPFILE,但没有使用SPFILE。
An ALTER SYSTEM command or an internal self-tuning mechanism requested a write to the SPFILE but no SPFILE was in use.
- 状态: 已验证。
- 分析: 一般是用ALTER SYSTEM命令修改参数时,使用scope=spfile选项进行修改,但是当前实例不是以SPFILE启动的。
-
措施: 使用SPFILE重新启动实例,或执行ALTER SYSTEM SET SPFILE。
Re-start the instance using an SPFILE, or execute ALTER SYSTEM SET SPFILE.
- 如果仍想用scope=spfile修改参数,那么则需用SPFILE文件重新启动实例,或者直接用命令
alter system set spfile = 'spfile文件在操作系统中的位置';
。
- 如果仍想用scope=spfile修改参数,那么则需用SPFILE文件重新启动实例,或者直接用命令
-
备注:
-
PFILE启动init.ora参数文件默认位置:
$ORACLE_HOME/dbs/init$ORACLE_SID.ora (Unix)
%ORACLE_HOME%\database\init%ORACLE_SID%.ora (Windows) -
SPFILE文件初始默认位置:
$ORACLE_HOME/dbs/spfile$ORACLE_SID.ora (Unix)
%ORACLE_HOME%\database\spfile%ORACLE_SID%.ora (Windows) -
根据PFILE文件创建SPFILE文件:
create spfile from pfile;-- 按默认位置找pfile
create spfile from pfile = '指定一个其它文件路径';- 根据SPFILE文件创建PFILE文件:
create pfile from spfile;-- 按默认位置找spfile
create pfile from spfile = '指定一个其它文件路径';
-
ORA-39083: 对象类型 (对象类型名) 创建失败, 出现错误:\n(错误描述)\n(失败的sql为):\n(SQL语句)
ORA-39083: Object type string failed to create with error:\nstring\nFailing sql is:\nstring
原因1: 检查原始错误代码以确定实际原因。
Examine original error code to determine actual cause
- 状态: 已验证。
-
分析: 此项异常只是一个桥梁,需关注“出现错误”后的实际对应错误编码和执行失败的SQL语句,如下例所示,为在执行impdp导入数据时产生的异常:
-- 此时出现的ORA-39083不需要关注,只需分析后边的ORA-14048及失败的SQL语句
……
……
ORA-39083: 对象类型 CONSTRAINT 创建失败, 出现错误:
ORA-14048: 分区维护操作不能与其他操作组合
失败的 sql 为:
ALTER INDEX "C##LY"."SYS_C00136360" UNUSABLE ENABLE
……
…… -
措施: 原始错误代码将包含更多信息(分析原始错误代码,具体情况具体对待)。
Original error code will contain more information
ORA-39151: 表 ("String"."String"=>["SCHEMA名"."表名"])已存在。由于TABLE_EXISTS_ACTION参数值设置为SKIP, 将跳过所有相关元数据和数据
ORA-39151: Table "String"."String" exists. All dependent metadata and data will be skipped due to table_exists_action of skip
原因1: 相关表已存在。
- 状态: 已验证,疑未记录在ORACLE异常文档中。
-
分析: 不一定是错误,某种程度上是一个ORACLE的提示警告信息,在利用ORACLE的impdp命令导入表的时候可能遇到,是因为出现dump文件中的需要导入的表已经在数据库用户schema下存在了,而你在使用impdp命令时未指定TABLE_EXISTS_ACTION的参数值,ORACLE虽然默认将值设置为了SKIP,但它发现有冲突的表仍然提示告诉你此处需要根据实际情况自主选择参数值,如下例所示:
-- 创建测试表
create table ora_39151(a number);
-- windows系统cmd命令窗口执行导出ora_39151的dump文件
expdp C##LY/密码@XE tables=ora_39151 dumpfile=ora_39151.dmp directory=data_pump_dir logfile=expdp_ora_39151.log
-- 测试导入
impdp C##LY/密码@XE tables=ora_39151 dumpfile=ora_39151.dmp directory=data_pump_dir logfile=impdp_ora_39151.log
-- 得到异常,impdp_ora_39151.log信息如下所示
;;;
Import: Release 11.2.0.2.0 - Production on 星期四 8月 31 20:33:27 2017 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
;;;
连接到: Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
已成功加载/卸载了主表 "C##LY"."SYS_IMPORT_TABLE_01"
启动 "C##LY"."SYS_IMPORT_TABLE_01": C##LY/********@XE tables=ora_39151 dumpfile=ora_39151.dmp directory=data_pump_dir logfile=impdp_ora_39151.log;
处理对象类型 TABLE_EXPORT/TABLE/TABLE
ORA-39151: 表 "C##LY"."ORA_39151" 已存在。由于跳过了 table_exists_action, 将跳过所有相关元数据和数据。
处理对象类型 TABLE_EXPORT/TABLE/TABLE_DATA
作业 "C##LY"."SYS_IMPORT_TABLE_01" 已经完成, 但是有 1 个错误 (于 20:33:31 完成) -
措施: 分析实际情况,判断是否需要导入dump文件中对应冲突表的元数据及数据信息。
-
如果确定不导入此类冲突表的数据,则不用进行任何操作,可忽视上面的错误,当然加上TABLE_EXISTS_ACTION=skip,亦可不出现错误,但任然会有提示信息:
-- 设置skip值重新测试导入
impdp C##LY/密码@XE tables=ora_39151 dumpfile=ora_39151.dmp directory=data_pump_dir logfile=impdp_ora_39151.log
-- 未得到异常,impdp_ora_39151.log信息如下所示
;;;
Import: Release 11.2.0.2.0 - Production on 星期四 8月 31 20:40:44 2017 Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
;;;
连接到: Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
已成功加载/卸载了主表 "C##LY"."SYS_IMPORT_TABLE_01"
启动 "C##LY"."SYS_IMPORT_TABLE_01": C##LY/********@XE tables=ora_39151 dumpfile=ora_39151.dmp directory=data_pump_dir logfile=impdp_ora_39151.log table_exists_action=skip
处理对象类型 TABLE_EXPORT/TABLE/TABLE
表 "C##LY"."ORA_39151" 已存在。由于跳过了 table_exists_action, 将跳过所有相关元数据和数据。
处理对象类型 TABLE_EXPORT/TABLE/TABLE_DATA
作业 "C##LY"."SYS_IMPORT_TABLE_01" 已于 20:40:46 成功完成 如果确定要导入此类冲突表的数据甚至元数据,则需重新执行导入操作,根据备注的描述选择其它参数进行处理。
-
-
备注: TABLE_EXISTS_ACTION参数值:
- SKIP: 表示跳过此表继续处理下个对象。
- APPEND: 表示在现有表数据行后追加dump文件中数据。
- TRUNCATE: 表示删除现有表中数据,然后导入dump文件中数据。
- REPLACE: 表示删除现有的表,然后从dump文件创建该表并导入数据。
持续更新中,可参见https://hnuhell.gitbooks.io/oracle_errmg/content/或https://hnuhell.github.io/Oracle_ERRMG/上的页面,博客更新较慢
作者:滚雪球俱乐部-何理利
出处: http://www.cnblogs.com/snowballed/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
如有疑问, 可邮件(he.lili1@ztesoft.com)咨询。