Oracle的資料型別:char/varchar2
char
http://blog.csdn.net/NinGoo/archive/2006/12/16/1445922.aspx
char型別儲存定長字串,最小長度為1位元組(或字元數),最長2000位元組(或字元數),如果不指定,則預設為1。
SQL> create table t(name char);
表已建立。
SQL> desc t;
名稱 是否為空? 型別
----------------------------------------- -------- ----------------------------
NAME CHAR(1)
SQL> create table t(name char(2001));
create table t(name char(2001))
*
第 1 行出現錯誤:
ORA-00910: 指定的長度對於資料型別而言過長
如果插入的字串長度不足,會以空格填充。如果超過長度,則會報錯。
SQL> insert into t values('aa');
insert into t values('aa')
*
第 1 行出現錯誤:
ORA-12899: 列 "SYS"."T"."NAME" 的值太大 (實際值: 2, 最大值: 1)
下面是例子展示了關於char型別的插入後續空格值的問題:
SQL> create table t(name char(20));
表已建立。
SQL> insert into t values('a');
已建立 1 行。
SQL> insert into t values('a ');
已建立 1 行。
SQL> select '"'||name||'"' from t where name='a';
'"'||NAME||'"'
----------------------
"a "
"a "
SQL> select '"'||name||'"' from t where name='a ';
'"'||NAME||'"'
----------------------
"a "
"a "
SQL> insert into t values(' a');
已建立 1 行。
SQL> select '"'||name||'"' from t where name='a';
'"'||NAME||'"'
----------------------
"a "
"a "
SQL> select '"'||name||'"' from t where name=' a';
'"'||NAME||'"'
----------------------
" a "
可以看到,如果插入的字串最後帶有空格,在查詢的時候是會將右邊的空格刪除後再來比較的,這一點在開發時需要注意。
varchar2和varchar
varchar2和varchar是同義詞,都是指變長字串型別。但是由於某種原因,varchar可能在後續版本中改變varchar的意思還是怎麼的,oracle建議使用varchar2。
在使用varchar2型別時必須指定其長度(1~2000位元組或字元數),不能像char一樣省略,雖然concepts文件上說其預設為1。這裡不知道oracle為什麼會這樣實現,我認為這應該算是一個缺陷。
SQL> drop table t;
表已刪除。
SQL> create table t(name varchar);
create table t(name varchar)
*
第 1 行出現錯誤:
ORA-00906: 缺失左括號
SQL> create table t(name varchar2);
create table t(name varchar2)
*
第 1 行出現錯誤:
ORA-00906: 缺失左括號
由於varchar2不會在短於指定長度的字串後面補齊空格,所以char型別中的後續空格問題不會在varchar2型別中發生。
SQL> create table t(name varchar2(20));
表已建立。
SQL> insert into t values('a');
已建立 1 行。
SQL> insert into t values('a ');
已建立 1 行。
SQL> select '"'||name||'"' from t where name='a';
'"'||NAME||'"'
----------------------
"a"
SQL> select '"'||name||'"' from t where name='a ';
'"'||NAME||'"'
----------------------
"a "
關於字元型資料的長度問題
前面在說到char/varchar2型別時,指定其長度可能是1位元組或者1個字元數。在不同的編碼方式中,一個字元可能佔1位元組,2位元組,3位元組甚至4位元組。
SQL> select name,value$ from props$ where name='NLS_CHARACTERSET';
NAME VALUE$
------------------------------ ------------------------------
NLS_CHARACTERSET ZHS16GBK
SQL> create table t(name char(1 byte));
表已建立。
SQL> insert into t values('測');
insert into t values('測')
*
第 1 行出現錯誤:
ORA-12899: 列 "SYS"."T"."NAME" 的值太大 (實際值: 2, 最大值: 1)
SQL> create table t(name char(1 char));
表已建立。
SQL> insert into t values('測');
已建立 1 行。
SQL> create table t(name char(1));
表已建立。
SQL> insert into t values('測');
insert into t values('測')
*
第 1 行出現錯誤:
ORA-12899: 列 "SYS"."T"."NAME" 的值太大 (實際值: 2, 最大值: 1)
可以看到,由於一個漢字佔兩個byte,如果char/varchar2的長度是按byte計算的,那麼就無法插入,如果是按字元數計算的,則可以插入。而在預設情況下,oracle是按byte計算長度的,這是由於引數nls_length_semantics的預設值是byte。
SQL> show parameter nls_length
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
nls_length_semantics string BYTE
在資料字典中,oracle還是會將按字元數計算的長度,按照系統當前的字符集選擇,轉換成按位元組計算的長度。由於我目前的測試系統中使用的ZHS16GBK字符集是定長字符集,每個字元佔兩個位元組,所以這裡data length為2。在一些變長字符集中,比如UTF8,則是4(UTF8中一個字元最長佔4個位元組)
SQL> drop table t;
表已刪除。
SQL> create table t(name char(1 char));
表已建立。
SQL> select TABLE_NAME,COLUMN_NAME,DATA_TYPE,DATA_LENGTH from dba_tab_columns where
table_name='T' a
nd wner=user;
TABLE_NAME COLUMN_NAM DATA_TYPE DATA_LENGTH
---------- ---------- ---------- -----------
T NAME CHAR 2
但是,oracle在判斷插入的時候不是以dba_tab_columns中記錄的data_length來做為限制條件的。看看UTF8下的試驗結果:
SQL> select name,value$ from props$ where name='NLS_CHARACTERSET';
NAME VALUE$
------------------------------ ------------------------------
NLS_CHARACTERSET AL32UTF8
SQL> drop table t;
表已刪除。
SQL> create table t(name char(1 char));
表已建立。
SQL> select TABLE_NAME,COLUMN_NAME,DATA_TYPE,DATA_LENGTH from dba_tab_columns where
2 table_name='T' and wner=user;
TABLE_NAME COLUMN_NAM DATA_TYPE DATA_LENGTH
---------- ---------- ---------- -----------
T NAME CHAR 4
SQL> insert into t values('aa');
insert into t values('aa')
*
第 1 行出現錯誤:
ORA-12899: 列 "SYS"."T"."NAME" 的值太大 (實際值: 2, 最大值: 1)
SQL> insert into t values('a');
已建立 1 行。
SQL> insert into t values('測');
已建立 1 行。
SQL> select dump(name) from t;
DUMP(NAME)
--------------------------------------------------------------------------------
Typ=96 Len=1: 97
Typ=96 Len=3: 230,181,139
可以看到,一個英文字元佔一個位元組,那麼'aa'只佔兩個位元組,卻無法插入。'測'佔3個位元組,卻能插入。所以在判斷插入的資料是否符合長度要求時,oracle會根據定義的資料型別是按位元組還是按字元數,然後參考系統當前的字符集設定來做出正確的判斷。
實際上,oracle提供的求字串長度的函式,返回的也是字元個數,而非位元組數:
SQL> select length('a') from dual;
LENGTH('A')
-----------
1
SQL> select length('測') from dual;
LENGTH('測')
------------
1
而lengthb返回的才是位元組數:
SQL> select lengthb('a') from dual;
LENGTHB('A')
------------
1
SQL> select lengthb('測') from dual;
LENGTHB('測')
-------------
3
Oracle裡Varchar、varchar2的引數(byte和char)的區別測試 Oracle裡Varchar、varchar2的引數(byte和char)的區別測試 1 看一下語法圖 2 下面進行sqlplus的測試,使用scott/tiger帳號。 SQL> create table test(name varchar(5 byte),namec varchar(5 char));表已建立。 SQL> insert into test(name) values('12345'); 已建立 1 行。 SQL> insert into test(name) values('123456'); insert into test(name) values('123456') 第 1 行出現錯誤: ORA-12899: 列 "SCOTT"."TEST"."NAME" 的值太大 (實際值: 6, 最大值: 5) SQL> insert into test(name) values('天津'); 已建立 1 行。 SQL> insert into test(name) values('天津市'); insert into test(name) values('天津市') 第 1 行出現錯誤: ORA-12899: 列 "SCOTT"."TEST"."NAME" 的值太大 (實際值: 6, 最大值: 5) SQL> insert into test(namec) values('12345'); 已建立 1 行。 SQL> insert into test(namec) values('123456'); insert into test(namec) values('123456') 第 1 行出現錯誤: ORA-12899: 列 "SCOTT"."TEST"."NAMEC" 的值太大 (實際值: 6, 最大值: 5) SQL> insert into test(namec) values('天津'); 已建立 1 行。 SQL> insert into test(namec) values('天津市'); 已建立 1 行。 SQL> insert into test(namec) values('天津市北京'); 已建立 1 行。 SQL> insert into test(namec) values('天津市北京市'); insert into test(namec) values('天津市北京市') 第 1 行出現錯誤: ORA-12899: 列 "SCOTT"."TEST"."NAMEC" 的值太大 (實際值: 6, 最大值: 5) SQL> select * from test; NAME NAMEC ----- ---------- 12345 天津 12345 天津 天津市 天津市北京 已選擇6行。 SQL> 3 分析 由於一個漢字在我的GBK系統裡佔用2個位元組,所以byte的只能插入2個漢字,而char的可以插入5個漢字。 所以byte 就是位元組數,對於漢字,GBK佔用2個位元組,如果是UTF-8則佔用3個位元組。 為了充分利用4000個的上限,給自己減少麻煩,建議儲存含有中文文字的欄位時,採用char型別。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14710393/viewspace-754870/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- LightDB 22.4 新特性之完全相容Oracle varchar2資料型別Oracle資料型別
- MySQL資料型別操作(char與varchar)MySql資料型別
- std::cout 輸出 unsigned char型別資料型別
- Oracle 資料型別Oracle資料型別
- Oracle的number資料型別Oracle資料型別
- 【轉】ORACLE資料型別Oracle資料型別
- Oracle anydata資料型別Oracle資料型別
- ORACLE NUMBER資料型別Oracle資料型別
- Oracle資料型別對應Java型別Oracle資料型別Java
- const char* 型別不能用於初始化char* 型別實體型別
- MySQL中資料型別(char(n)、varchar(n)、nchar(n)、nvarchar(n)的區別)MySql資料型別
- Oracle OCP(19):資料型別Oracle資料型別
- 【C++】CONST CHAR*型別的值不能用於初始化CHAR*型別的實體C++型別
- E0144 "const char *" 型別的值不能用於初始化 "char *" 型別的實體型別
- Oracle字串資料型別簡述Oracle字串資料型別
- CAPL指令碼中常用到的資料型別轉換——數字型別(int/double)和字串型別(char array)指令碼資料型別字串
- Oracle 中varchar2 和nvarchar2區別Oracle
- NTMySQL中varchar和char型別的區別heeMySql型別
- [20191219]oracle timestamp資料型別的儲存.txtOracle資料型別
- 【VS2019 C++】"const char *" 型別的值不能用於初始化 "char *" 型別的實體C++型別
- Oracle和sqlserver資料型別對應OracleSQLServer資料型別
- Oracle基本資料型別儲存格式淺析——RAW型別Oracle資料型別
- 當char型變數遇上char*型的指標變數指標
- 資料型別與函式索引-Oracle篇資料型別函式索引Oracle
- Oracle long轉為varchar2Oracle
- C# - char型別的一些介紹C#型別
- oracle資料庫事務transaction 不同的鎖lock型別Oracle資料庫型別
- Oracle BLOB型別的資料如何檢視和下載?Oracle型別
- [20241009]oracle timestamp with time zone資料型別的儲存.txtOracle資料型別
- js資料型別之基本資料型別和引用資料型別JS資料型別
- 【筆記】VS2017中出現 "const char *" 型別的值不能用於初始化 "char *" 型別的實體筆記型別
- 資料型別: 資料型別有哪些?資料型別
- 1.1. Oracle 資料庫使用者型別Oracle資料庫型別
- VS2019【C++報錯】E0144"const char *" 型別的值不能用於初始化 "char *" 型別的實體C++型別
- Java中的基本資料型別與引用資料型別Java資料型別
- VS中”LPTSTR" 型別的值不能用於初始化 "char *" 型別的實體型別
- CString與LPCWSTR、LPSTR、char*、LPWSTR等型別的轉換型別
- 區別值型別資料和引用型別資料型別
- SAP CDS view 如何將 CHAR 型別的資料欄位和當前系統日期比較View型別