ORACLE IMP ORA-00910 出錯處理案例

paulyibinyi發表於2009-05-02

環境 源庫AIX+9.2.0.4  新庫solaris+9.2.0.8 

匯入出錯提示是以下部分:
IMP-00017: following statement failed with ORACLE error 910:
 "CREATE TABLE "T_CSL_DYNAITEMDATAENTRY" ("FID" VARCHAR2(44) NOT NULL ENABLE,"
 " "FITEMDATAID" VARCHAR2(44) NOT NULL ENABLE, "FITEMID" VARCHAR2(44) NOT NUL"
 "L ENABLE, "FKEYNUMBER" NVARCHAR2(500) NOT NULL ENABLE, "FKEYNAME" NVARCHAR2"
 "(500) NOT NULL ENABLE, "FDATAELEMENT" NUMBER(10, 0) NOT NULL ENABLE, "FVALU"
 "ETYPE" NUMBER(10, 0) NOT NULL ENABLE, "FYEAR" NUMBER(10, 0) NOT NULL ENABLE"
 ", "FPERIOD" NUMBER(10, 0) NOT NULL ENABLE, "FVALUE" NUMBER(21, 6), "FDYNAIT"
 "EMTYPE" NUMBER(10, 0), "FTEXTVALUE" NVARCHAR2(4000), "FGRADENUMBER" VARCHAR"
 "2(80))  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 STORAGE(INITIAL 15728"
 "640 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT) TABLESPACE "EAS_D_CH"
 "INAMOBILE_STANDARD" LOGGING NOCOMPRESS"
IMP-00003: ORACLE error 910 encountered
ORA-00910: specified length too long for its datatype

經過詳細檢查匯入日誌只有要NVARCHAR2(4000)的欄位型別表都匯入不了,而且nvarchar2儲存的資料大部分是中文。

在原庫查詢
SQL> select name,VALUE$ from props$ where name in ('NLS_CHARACTERSET','NLS_NCHAR_CHARACTERSET');

NAME                           VALUE$
------------------------------ --------------------------------------------------------------------------------
NLS_CHARACTERSET               ZHS16GBK
NLS_NCHAR_CHARACTERSET         UTF8

在新庫查詢

SQL> select name,VALUE$ from props$ where name in ('NLS_CHARACTERSET','NLS_NCHAR_CHARACTERSET');

NAME                           VALUE$
------------------------------ --------------------------------------------------------------------------------
NLS_CHARACTERSET               ZHS16GBK
NLS_NCHAR_CHARACTERSET         AL16UTF16

可以看出原庫和新庫的國家字符集不同

透過查資料,得到以下答案

在建立資料庫時,我們可以指定字符集(CHARACTER SET)和國家字符集(NATIONAL CHARACTER SET)。
字符集用來儲存:
     CHAR, VARCHAR2, CLOB, LONG等型別資料
     用來標示諸如表名、列名以及PL/SQL變數等
     SQL和PL/SQL程式單元等
國家字符集用以儲存:
     NCHAR, NVARCHAR2, NCLOB等型別資料

utf-8和utf-16他們兩的字元範圍是完全相同的。
utf-8和utf-16是unicode的兩種編碼實現,都能完全表現unicode。
不同之處就在於:
utf8 對於ansi 字元 (英文字母,數字,符號) 用一個 byte ,但對中文字元就要 3個byte才行,甚至有要4個byte的漢字。
而一般 utf16 對 一般的 字元包括漢字都是2bytes。

所以原來儲存的欄位值更大,而新庫儲存的欄位值更小,導致nvarchar2型別的資料匯入出錯。

解決方法:
1.更改國家字符集由AL16UTF16為UTF8
  $ sqlplus ‘/ as sysdba’
  SQL> SHUTDOWN IMMEDIATE;
  SQL> STARTUP MOUNT EXCLUSIVE;
  SQL> ALTER SYSTEM ENABLE RESTRICTED SESSION;
  SQL> ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
  SQL> ALTER SYSTEM SET AQ_TM_PROCESSES=0;
  SQL> ALTER DATABASE OPEN;
  SQL> ALTER DATABASE NATIONAL CHARACTER SET INTERNAL_USE UTF8;
  SQL> SHUTDOWN IMMED
  用這種方法更改後,透過測試匯入一個有nvarchar2欄位型別表的資料,會出現亂碼,而且直接這樣修改國家字符集會存在風險,所以放棄。

2.重建資料庫,選擇國家字符集為UTF8,測試匯入一個有nvarchar2欄位型別表的資料正常。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7199859/viewspace-592423/,如需轉載,請註明出處,否則將追究法律責任。

相關文章