1. 程式人生 > >Oracle資料庫中漢字長度的問題

Oracle資料庫中漢字長度的問題

問題:

  varchar2(4000) abc;

  intert into table_name(abc) values('這裡有1500個漢字……');

  報錯:插入字元過長!經過測試 ,發現一個漢字佔3個字 節,所以會報錯。

  問題癥結:

  使用的字符集是UTF8,就會出現此錯誤!

  你可以使用命令檢視:

SQL> select * from v$nls_parameters where parameter='NLS_CHARACTERSET';

PARAMETER
------------------------------------------------
VALUE
------------------------------------------------
NLS_CHARACTERSET
AL32UTF8

  解決方法:

  建議使用ZHS16GBK字符集!

  執行此操作後,問題即可得以解決。

SQL> SHUTDOWN IMMEDIATE;  
SQL> STARTUP MOUNT;
SQL> ALTER SYSTEM ENABLE RESTRICTED SESSION;
SQL> ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
SQL> ALTER DATABASE OPEN;
SQL> ALTER DATABASE CHARACTER SET AL32UTF8/ZHS16GBK;
SQL> SHUTDOWN IMMEDIATE;
SQL> STARTUP;



漢字在oracle中佔用位元組數

一,漢字在oracle中佔用位元組數

一定要在建庫的時候就選擇好字符集,否則可能給後續的開發或者遷移帶來問題。在開發中字符集問題通常會導致應用層面上的字元越界或者亂碼問題。

先來看看2個使用不同字符集的資料庫:

先來看server1:

SQL> select * from v$nls_parameters a ;

 

PARAMETER                                                       VALUE

---------------------------------------------------------------- ----------------------------------------------------------------

NLS_LANGUAGE                                                    SIMPLIFIED CHINESE

NLS_TERRITORY                                                   CHINA

NLS_CURRENCY                                                    RMB

NLS_ISO_CURRENCY                                                CHINA

NLS_NUMERIC_CHARACTERS                                          .,

NLS_CALENDAR                                                    GREGORIAN

NLS_DATE_FORMAT                                                 DD-MON-RR

NLS_DATE_LANGUAGE                                               SIMPLIFIED CHINESE

NLS_CHARACTERSET                                                WE8ISO8859P1

NLS_SORT                                                        BINARY

NLS_TIME_FORMAT                                                 HH.MI.SSXFF AM

NLS_TIMESTAMP_FORMAT                                            DD-MON-RR HH.MI.SSXFF AM

NLS_TIME_TZ_FORMAT                                              HH.MI.SSXFF AM TZR

NLS_TIMESTAMP_TZ_FORMAT                                         DD-MON-RR HH.MI.SSXFF AM TZR

NLS_DUAL_CURRENCY                                               RMB

NLS_NCHAR_CHARACTERSET                                          AL16UTF16

NLS_COMP                                                        BINARY

NLS_LENGTH_SEMANTICS                                            BYTE

NLS_NCHAR_CONV_EXCP                                             FALSE

 

19 rows selected

 

SQL> select '漢字' from dual;

 

'??'

------



 

再看看server2:

SQL> select * from v$nls_parameters a ;

 

PARAMETER                                                       VALUE

---------------------------------------------------------------- ----------------------------------------------------------------

NLS_LANGUAGE                                                    SIMPLIFIED CHINESE

NLS_TERRITORY                                                   CHINA

NLS_CURRENCY                                                    RMB

NLS_ISO_CURRENCY                                                CHINA

NLS_NUMERIC_CHARACTERS                                          .,

NLS_CALENDAR                                                    GREGORIAN

NLS_DATE_FORMAT                                                 DD-MON-RR

NLS_DATE_LANGUAGE                                               SIMPLIFIED CHINESE

NLS_CHARACTERSET                                                AL32UTF8

NLS_SORT                                                        BINARY

NLS_TIME_FORMAT                                                 HH.MI.SSXFF AM

NLS_TIMESTAMP_FORMAT                                            DD-MON-RR HH.MI.SSXFF AM

NLS_TIME_TZ_FORMAT                                              HH.MI.SSXFF AM TZR

NLS_TIMESTAMP_TZ_FORMAT                                         DD-MON-RR HH.MI.SSXFF AM TZR

NLS_DUAL_CURRENCY                                               RMB

NLS_NCHAR_CHARACTERSET                                          AL16UTF16

NLS_COMP                                                        BINARY

NLS_LENGTH_SEMANTICS                                            BYTE

NLS_NCHAR_CONV_EXCP                                             FALSE

 

19 rows selected

 

SQL> select '漢字' from dual;

 

'漢字'

------

漢字

 

通過比較上述兩個資料庫的區別,發現他們的NLS_CHARACTERSET不同,一個是WE8ISO8859P1,而另外一個是AL32UTF8。WE8ISO8859P1是單位元組8位字符集,AL32UTF8是變長多位元組編碼。

現在的客戶端的字符集為:SIMPLIFIED CHINESE_CHINA.ZHS16GBK

WE8ISO8859P1沒有漢字編碼,一般來講,有中文字元就不應該使用這個字符集,雖然修改客戶端和伺服器端相同時可以解決亂碼問題。

有關漢字在oracle中佔用的位元組數問題:

在WE8ISO8859P1字符集下,一個漢字佔了1個位元組。

在AL32UTF8字符集下面,一個漢字佔了3個位元組。

在ZHS16GBK是佔用了2個位元組。

Varchar2,varchar,nvarchar2均為變長字元型別,char則是固定長度。

用vsize函式來看的話很明顯:

Server1:

SQL> select vsize('漢') from dual;

 

 VSIZE('?')

-----------

         1

Server2:

SQL> select vsize('漢') from dual;

 

 VSIZE('漢')

-----------

         3

而用length來看,則均為1:

Server1:

SQL> select length('漢') from dual;

 

 LENGTH('?')

------------

          1

Server2:

SQL> select length('漢') from dual;

 

 LENGTH('漢')

------------

          1

 

下面具體來看個對比:

Server1和server2中均建立下面的表:

create table t_test_var

(

v_char2 char(2),

v_char3 char(3),

v_varchar22 varchar2(2),

v_varchar23 varchar2(3),

v_varchar2 varchar(2),

v_varchar3 varchar(3),

v_nvarchar22 nvarchar2(2),

v_nvarchar23 nvarchar2(3)

);

然後分別在兩個資料庫中插入測試資料:

Server1:

SQL> insert into t_test_var values ('我','我','我','我','我','我','我','我');

 

1 row inserted

SQL> insert into t_test_var values ('我們','我們','我們','我們','我們','我們','我們','我們');

 

1 row inserted

SQL> insert into t_test_var values ('我們是','我們是','我們是','我們是','我們是','我們是','我們是','我們是');

 

insert into t_test_var values ('我們是','我們是','我們是','我們是','我們是','我們是','我們是','我們是')

 

ORA-12899: value too large for column "TEST"."T_TEST_VAR"."V_CHAR2" (actual: 3, maximum: 2)

 

說明server1中char用一個位元組來儲存一個漢字。

修改一下最後一條插入語句,使得char型別不越界:

 

SQL> insert into t_test_var values ('我們','我們是','我們是','我們是','我們是','我們是','我們是','我們是');

 

insert into t_test_var values ('我們','我們是','我們是','我們是','我們是','我們是','我們是','我們是')

 

ORA-12899: value too large for column "TEST"."T_TEST_VAR"."V_VARCHAR22" (actual: 3, maximum: 2)

 

SQL>

則說明了server1中的varchar2型別也是一個位元組儲存一個漢字,再次修改:

SQL> insert into t_test_var values ('我們','我們是','我們','我們是','我們是','我們是','我們是','我們是');

 

insert into t_test_var values ('我們','我們是','我們','我們是','我們是','我們是','我們是','我們是')

 

ORA-12899: value too large for column "TEST"."T_TEST_VAR"."V_VARCHAR2" (actual: 3, maximum: 2)

則說明varchar也是一個漢字佔一個位元組儲存空間,繼續修改:

 

SQL> insert into t_test_var values ('我們','我們是','我們','我們是','我們','我們是','我們是','我們是');

 

insert into t_test_var values ('我們','我們是','我們','我們是','我們','我們是','我們是','我們是')

 

ORA-12899: value too large for column "TEST"."T_TEST_VAR"."V_NVARCHAR22" (actual: 3, maximum: 2)

則說明nvarchar2也是一個漢字佔一個位元組儲存空間。

這是因為在WE8ISO8859P1字元中,根本沒有漢字編碼。所以得出以上的實驗結果。

 

再來看看Server2:

SQL> insert into t_test_var values ('我','我','我','我','我','我','我','我');

 

insert into t_test_var values ('我','我','我','我','我','我','我','我')

 

ORA-01401: inserted value too large for column

SQL> insert into t_test_var values ('我們','我們','我們','我們','我們','我們','我們','我們');

 

insert into t_test_var values ('我們','我們','我們','我們','我們','我們','我們','我們')

 

ORA-01401: inserted value too large for column

SQL> insert into t_test_var values ('我們是','我們是','我們是','我們是','我們是','我們是','我們是','我們是');

 

insert into t_test_var values ('我們是','我們是','我們是','我們是','我們是','我們是','我們是','我們是')

 

ORA-01401: inserted value too large for column

 

SQL> select cast('漢' as char(1)) from dual;

 

select cast('漢' as char(1)) from dual

 

ORA-25137: Data value out of range

 

SQL> select cast('漢' as char(2)) from dual;

 

select cast('漢' as char(2)) from dual

 

ORA-25137: Data value out of range

 

SQL> select cast('漢' as char(3)) from dual;

 

CAST('漢'ASCHAR(3))

-------------------



SQL> insert into t_test_var (v_varchar22) values ('漢');

 

insert into t_test_var (v_varchar22) values ('漢')

 

ORA-01401: inserted value too large for column

SQL> insert into t_test_var (v_varchar23) values ('漢');

 

1 row inserted

相關推薦

Oracle資料庫漢字長度的問題

問題:   varchar2(4000) abc;   intert into table_name(abc) values('這裡有1500個漢字……');   報錯:插入字元過長!經過測試 ,發現一個漢字佔3個字 節,所以會報錯。   問題癥結:   使用的字符集是UT

oracle資料庫漢字轉化成拼音

select FN_GETPY('漢字',1) from dual; --HANZI select FN_GETPY('漢字',2) from dual; --HanZi select FN_GETPY('漢字',3) from dual;--hz select FN_

匯入Oracle資料庫漢字都是問號

iamlaosong文 匯入伺服器Oracle資料庫中漢字都是問號“?”,查資料庫的字符集沒問題,那麼就是客戶端的問題。 查Oracle使用者的環境變數,發現沒有設定NLS_LANG,在.bash_p

更改oracle資料庫某個表的某個欄位的資料型別和長度

不廢話需求:在plsql中更改oracle資料庫中的info_agency表中的county欄位的資料型別 為varchar 長度為255實現:alter TABLE INFO_AGENCY MODIFY (county VARCHAR(255));親用 則 可用

MySQL、SQL server 、Oracle資料庫查詢所有的資料庫,查詢指定資料庫所有表名,查詢所有的欄位的名字

MySQL中查詢所有資料庫名和表名 1.查詢所有資料庫 show databases; 2.查詢指定資料庫中所有表名 select table_name from information_schema.tables where table_schema='database_name' a

mybatis 在oracle資料庫插入資料時獲取自增ID sequence序列

在oracle中sequence就是序號,每次取的時候它會自動增加。sequence與表沒有關係。 Create Sequence 首先要有CREATE SEQUENCE或者CREATE ANY SEQUENCE許可權。 建立語句如下: CREATE SEQUEN

Oracle資料庫複製表結構和表資料

1. 複製表結構及其資料: create table new_table as select * from old_table 2. 只複製表結構: create table new_tableas select * from old_tablewhere 1=2; 或者:

兩個Oracle資料庫的表的結構和資料的複製方法

1. 複製表結構及其資料: create table table_name_new as select * from table_name_old 2. 只複製表結構: create table table_name_new as select * from table_name_old

日期型別的資料在Oracle資料庫的儲存和查詢

使用Oracle資料庫,mybatis的對映檔案中日期型別的資料,如果定義為<result column =“UPDATED_DATE" jdbcType =“DATE” property =“updatedDate”/>,即使在後臺你為日期賦予年月日時分秒,但儲存到資料庫中將只

oracle資料庫使用hibernate生成表不能正確建立表

最近在專案中使用hibernate的動態生成表,即將hbm2ddl.auto配置成update時,發現hibernate並沒有按照預設的生成規則生成相應的資料表資訊。但奇怪的是,只是部分表沒有生成,而其它的表即生成成功了。重新啟動專案,發現問題依舊。奇怪的是,雖然有些表沒有生成,但它相關聯的關聯表即生成了,而

PageHelper5.0在oracle資料庫使用

原理:         pageHelper會使用ThreadLocal獲取到同一執行緒中的變數資訊,各個執行緒之間的Threadlocal不會相互干擾,也就是Thread1中的ThreadLocal1之後獲取到Tr

plsql 儲存csv檔案 到oracle 資料庫

最近在用oracle資料庫,在使用plsql中遇到的一些問題。今天再記錄一下吧。 1、建表。目的是:被匯入到資料的儲存位置。 因為資料庫中曾經有過相同表結構的表,所以直接使用SQL建表。 -- T_FULL_DEVICE表 CREATE TABLE "XXXX"."T_FULL_DE

oracle資料庫選擇桌面類和伺服器類的區別

在以前的學習過程中,一直用到的都是sql server資料庫,之後接觸到了oracle資料庫。在安裝過程中,有兩個選項,桌面類和伺服器類,當時按照網上的安裝步驟,選擇了桌面類,後來公司裡他們安裝都是用的伺服器類,後來查了查兩者的區別。 桌面類――這種安裝方式一般適用於桌上型電腦和筆記本。它包含一

oracle 資料庫(建立、解鎖、授權、刪除)使用者

上文我們已經建立了名為orcl66的資料庫。 想要在資料庫中建立、修改使用者需要我們以管理員許可權登入到資料庫中。 首先我們通過sqlplus命令登入連線資料庫。 輸入sqlplus命令--使用者名稱: sys as sysdba (回車)--口令:(任意字元都可以登入) 登陸成功後就可以建立新使

Oracle資料庫對誤刪資料的恢復

如果一不小心對Oracle資料庫中的資料進行了誤刪除操作,那麼如何進行資料恢復呢(不考慮全庫備份和利用歸檔日誌)?如果使用的是9i以及之後的版本,那麼我們可以採用閃回技術對誤刪除的資料進行恢復。方式有兩種。 原理: 利用oracle提供的閃回方法,如果在刪除資料後還沒做大量的操作(只

Oracle資料庫使用者與模式的區別與聯絡

使用者與模式 使用者(user):Oracle使用者是用連線資料庫和訪問資料庫物件的。(使用者是用來連線資料庫訪問資料庫)。 模式(schema):模式是資料庫物件的集合。模式物件是資料庫資料的邏輯結構。(把資料庫物件用模式分開成不同的邏輯結構)。 使用者(user)與模式(schema)的

Oracle資料庫查詢結果集中保留兩位小數的問題

工作中遇到的Oracle資料庫欄位格式化問題,在此記錄  保留兩位小數主要分為兩種情況:  1.數字保留兩位小數;(小數點左側數字可能比較大,比如1234567890.12)  2.百分比保留兩位小數;(小數點左側數字數字小於等於100,比如98.76%) 現針對O

【程式碼全】使用SpringAOP編寫日誌記錄(插入oracle資料庫

程式碼較多,請耐心除錯 首先oracle資料庫表建立語句: drop table cmu_system_log;CREATE TABLE CMU_SYSTEM_LOG ( log_id INTEGER primary key , user_id INTEGER , username

Oracle--Oracle資料庫插入日期,日期帶有時分秒(java.util.Date型別)

       通過JDBC向oracle資料庫中插入時間型別時間時,可以直接向資料庫中插入java.sql.Date型別的時間,但是時間只包含年月日,沒有時分秒。如果需要通過JDBC向oracle中插入java.util.Date型別的時間,先將Date轉換成格式化字串,再進

oracle資料庫把表結構匯入到powerDesigner

在此介紹PowerDesigner連線Oracle資料庫,根據建立的資料來源進行E-R圖生成。詳細步驟如下: 1、啟動PowerDesigner 2、選單:File->Reverse Engineer ->Database 出來New Physical Dat