ORA-01502: index ‘string.string’ or partition of such index is in unusable state
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
ORA-01722: invalid number
The specified number was invalid.
显式转换:
-- 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.
ORA-01747: invalid user.table.column, table.column, or column specification
分析: 一般为在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 = '字段名'
;
specified initialization parameter cannot be modified
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: specified initialization parameter is not modifiable with this option
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 = &参数名小写;