持續更新中,可參見https://hnuhell.gitbooks.io/oracle_errmg/content/或https://hnuhell.github.io/Oracle_ERRMG/上的頁面。
ORA-00000 to ORA-00877
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: 當前會話被要求通過另一個會話設定一個跟蹤事件【ora12_ERRMG】
The current session was requested to set a trace event by another session.
措施: 內部使用;無需操作。
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 參數名=值 [scope=應用範圍]; scope需知: scope=both,表示修改會立即生效且會修改spfile檔案以確保資料庫在重啟後也會生效如果(以spfile啟動此項為預設值); scope=memory,表示修改會立即生效但不會修改spfile檔案,因此重啟後失效(以pfile啟動此項為預設值,且只可設定這個值); scope=spfile,表示只修改spfile檔案,在重啟資料庫後才生效(對應靜態參數則只可設定此項值,設定其它值會報錯: ORA-02095: specified initialization parameter cannot be modified)。 */ -- 查看"是否可用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 || '=&' || '新的參數值;"更改參數並將在之後的會話中生效。' 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') a where name = 'sessions';
如果判斷確定SESSIONS值合理,則需分析確定產生大量會話的原因,是否相關程式碼建立了串連未釋放。或者其它原因等。【待完善】
備忘: 參數SESSIONS:
| 屬性 |
描述 |
| 參數類型 |
Integer |
| 預設值 |
派生公式: (1.1 * PROCESSES) + 5) [11gR1,11gR2] (1.5 * PROCESSES) + 22 |
| 可修改(不用重啟及時生效) |
否 [11gR2,12cR1] 可用ALTER SYSTEM修改 |
| 取值範圍 |
1~2^31 [11gR1,11gR2] 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:
| 屬性 |
描述 |
| 參數類型 |
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:
| 屬性 |
描述 |
| 參數類型 |
Integer |
| 預設值 |
40~作業系統依賴數 [10gR2,11gR1] 100 [11gR2,12cR1] 該值是派生的,它通常取決於警報日誌中報告的核心數。 |
| 可修改(不用重啟及時生效) |
否 |
| 取值範圍 |
6~作業系統依賴數 |
| 基礎參數 |
是 |
| Oracle即時應用叢集 |
多個執行個體可以具有不同的值。 |
PROCESSES指定可以同時串連到Oracle的最大作業系統使用者進程數。它的值應允許所有後台進程運行,如鎖,作業隊列進程和並存執行進程。
該參數派生了SESSIONS和TRANSACTIONS參數的預設值。因此,如果更改PROCESSES的值,則應評估是否要調整這些派生參數的值。 ORA-01500 to ORA-02098 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