ORA-01500 to ORA-02098
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 = &参数名小写;