DM8 varchar型別長度
我們在資料遷移或是往資料表中匯入中文字元時,經常會出現varchar型別超過字元長度的報錯,今天我們就來分析一下varchar資料型別長度的佔比。
在說varchar型別之前先來說說char資料型別。char型別是指定長的字串。在基表中,定義char型別的列時,其最大儲存長度由資料庫頁面大小決定,可以指定一個不超過其最大儲存長度的正整數作為字元長度,例如:char(100)。如果未指定長度,預設為1。char資料型別最大儲存長度和頁面大小有關,但是,在表示式計算中,該型別的長度上限不受頁面大小限制為32767。
char 最大儲存長度和頁面大小的對應關係 | |
資料庫頁面大小 |
實際最大長度 |
4K |
1900 |
8K |
3900 |
16K |
8000 |
32K |
8188 |
這個限制長度只針對建表的情況,在定義變數的時候,可以不受這個限制長度的限制。
varchar 資料型別是指的變長字串,用法類似char資料型別,可以指定一個不超過8188的正整數作為字元長度,例如:varchar(100)。如果未指定長度,預設為8188。在基表中,當沒有指定USINGLONG ROW 儲存選項時,插入varchar資料型別的實際最大儲存長度由資料庫頁面大小決定。
在使用DMINIT初始化資料庫的時候,有兩個引數CHARSET/UNICODE_FLAG和LENGTH_IN_CHAR跟字符集相關。
Ø CHARSET/UNICODE_FLAG :此參數列示了資料庫中所有資料的字符集,包括資料字典的字符集。需要注意的是,資料庫一旦初始化完成,字符集就將無法修改。我們可以使用select unicode來查詢當前資料庫的字符集種類,0代表gb18030,1代表UTF8。
Ø LENGTH_IN_CHAR :此引數決定了,資料庫中的varchar型別物件的長度是否以字元為單位。取值為1則設定為以字元為單位,將儲存長度值按照理論字元長度進行放大。取值為0則所有varchar型別物件的長度以位元組為單位。
測試環境 |
作業系統:Red Hat Enterprise Linux Server release 7.9 (Maipo) |
資料庫系統:DM Database Server 64 V8-4-2-38-21.07.02-142948-10018-ENT |
1. 當LENGTH_IN_CHAR=0,UNICODE_FLAG=0時 (字符集是gb18030,長度以位元組為單位)
SQL> create table test (name varchar(3)); executed successfully SQL> insert into test values (' 測'); affect rows 1
SQL> insert into test values (' 測a'); affect rows 1
SQL> insert into test values (' 測試'); insert into test values (' 測試'); [-6169]:Column [NAME] out of length. SQL> commit; executed successfully SQL> select name,length(name),lengthb(name) from test;
NAME LENGTH(NAME) LENGTHB(NAME) ---- ------------ ------------- 測 1 2 測a 2 3 |
當字符集是gb18030,長度以位元組為單位時,一個漢字佔兩個位元組,一個英文字元佔一個位元組。Varchar(1)表示1個位元組,因編碼為gb18030,一個漢字佔用兩個位元組。所以varchar長度為3時,實際可以錄入1個漢字(1*3=3),3個英文字元。
2. 當LENGTH_IN_CHAR=1,UNICODE_FLAG=0時 (字符集是gb18030,長度以字元為單位)
SQL> create table test (name varchar(3)); executed successfully SQL> insert into test values (' 測試'); affect rows 1
SQL> insert into test values (' 測試姓'); affect rows 1
SQL> insert into test values (' 測試姓名'); insert into test values (' 測試姓名'); [-6169]:Column [NAME] out of length. SQL> commit; executed successfully SQL> select name,length(name),lengthb(name) from test;
NAME LENGTH(NAME) LENGTHB(NAME) ------ ------------ ------------- 測試 2 4 測試姓 3 6 |
當字符集是gb18030,長度以字元為單位時,一個漢字佔兩個位元組,一個英文字元佔一個位元組。varchar表示2個位元組,因編碼為gb18030,一個漢字佔用兩個位元組。所以varchar長度為3時,實際可以錄入2個漢字(2*3=6),6個英文字元。
3. 當LENGTH_IN_CHAR=0,UNICODE_FLAG=1時(字符集是utf-8,長度以位元組為單位)
SQL> create table test (name varchar(3)); executed successfully SQL> insert into test values (' 測'); affect rows 1
SQL> insert into test values (' 測試'); insert into test values (' 測試'); [-6169]:Column [NAME] out of length. SQL> insert into test values (' 測a'); insert into test values (' 測a'); [-6169]:Column [NAME] out of length. SQL> commit; executed successfully SQL> select name,length(name),lengthb(name) from test;
NAME LENGTH(NAME) LENGTHB(NAME) ---- ------------ ------------- 測 1 3 |
當引數UNICODE_FLAG=1、LENGTH_IN_CHAR=0時。Utf8一個漢字佔用三個位元組,一個英文佔用一個位元組。varchar以位元組為單位,一個varchar等於一個位元組。
4. 當LENGTH_IN_CHAR=1,UNICODE_FLAG=1時(字符集是utf-8,長度以字元為單位)
SQL> create table test (name varchar(3)); executed successfully SQL> insert into test values (' 測試姓'); affect rows 1
SQL> insert into test values (' 測試姓名'); affect rows 1
SQL> insert into test values (' 測試姓名a'); insert into test values (' 測試姓名a'); [-6169]:Column [NAME] out of length. SQL> commit; executed successfully SQL> select name,length(name),lengthb(name) from test;
NAME LENGTH(NAME) LENGTHB(NAME) ------------ ------------ ------------- 測試姓 3 9 測試姓名 4 12 |
這裡我們會發現一個奇怪的情況,明明設定是varchar(3),為什麼可以插入4個漢字呢。這是因為在DM8中資料庫實際儲存資料是以位元組為單位。在lengtg_in_char=1且字符集為utf-8的時候,VARCHAR型別物件的實際存放的最大長度是VARCHAR型別定義的長度*4位元組。
也就是說,這裡一個varchar(3)的結構可以存放的資料為3*4=12個位元組。然而事實上UTF-8中的一個漢字一般只用佔用3個位元組,所以這裡我們可以插入12/3=4個漢字。
當引數UNICODE_FLAG=1、LENGTH_IN_CHAR=1時,varchar表示4個位元組,因編碼為uft8,一個漢字佔用三個位元組。所以varchar長度為3時,實際可以錄入4個漢字(3*4=12),12個英文字元。
5. 總結
當LENGTH_IN_CHAR=0的情況下,varchar()的長度是以位元組數為單位。這時我們只需要考慮漢字和全形字元所佔用位元組數,其中gb18030的一個漢字是兩個位元組,utf-8的一個漢字一般是三個位元組。如果插入資料的總位元組數大於varchar定義的長度,則會插入失敗。
當LENGTH_IN_CHAR=1的情況下,varchar()所能儲存的位元組數將會按照一定比例擴充套件。字符集為gb18030時varchar的位元組數等於定義長度*2,字符集為utf-8時varchar的位元組數為定義長度*4。
彙總表
varchar(1) 分類 |
所佔 位元組數 |
1 個漢字 佔用位元組數 |
1 個英文 佔用位元組數 |
儲存 漢字 |
儲存 英文 |
字符集是gb18030, 長度以位元組為單位 |
1 個位元組 |
2 個位元組 |
1 個位元組 |
0 個漢字 |
1 個英文 |
字符集是gb18030, 長度以字元為單位 |
2 個位元組 |
2 個位元組 |
1 個位元組 |
1 個漢字 |
2 個英文 |
字符集是uft8, 長度以位元組為單位 |
1 個位元組 |
3 個位元組 |
1 個位元組 |
0 個漢字 |
1 個英文 |
字符集是uft8, 長度以字元為單位 |
4 個位元組 |
3 個位元組 |
1 個位元組 |
1 個漢字 |
4 個英文 |
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31516603/viewspace-2780434/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- mysql中varchar型別最大長度測試MySql型別
- MySQL 中 VARCHAR 最大長度及 CHAR 和 VARCHAR 的區別MySql
- MySQL VARCHAR型別欄位到底可以定義多長MySql型別
- 例項操作mysql varchar型別求和MySql型別
- MySQL動態修改varchar長度的方法MySql
- 【YashanDB知識庫】kettle從DM8的number型別同步到YashanDB的varchar型別,存入是科學計數法形式的資料型別
- NTMySQL中varchar和char型別的區別heeMySql型別
- MySQL資料型別操作(char與varchar)MySql資料型別
- 資料庫text型別的長度?資料庫型別
- Oracle 修改欄位型別和長度Oracle型別
- mysql的varchar欄位最大長度真的是65535嗎?MySql
- mysql變長型別欄位varchar值更新變長或變短底層檔案儲存原理MySql型別
- Mysql BLOB、BLOB與TEXT區別及效能影響、將BLOB型別轉換成VARCHAR型別MySql型別
- MySQL int型別長度的意義是什麼MySql型別
- ORANCLE 資料已存在,修改欄位型別長度型別
- MySQL中資料型別(char(n)、varchar(n)、nchar(n)、nvarchar(n)的區別)MySql資料型別
- varchar和char的區別
- 【YashanDB知識庫】oracle dblink varchar型別查詢報錯記錄Oracle型別
- Mysql varchar型別欄位為什麼經常定義為255MySql型別
- LightDB 22.4 新特性之完全相容Oracle varchar2資料型別Oracle資料型別
- MySQL中CHAR和VARCHAR區別MySql
- [轉載] 詳解 MySQL int 型別的長度值問題MySql型別
- 【轉載】詳解 MySQL int 型別的長度值問題MySql型別
- 聯機重定義修改欄位型別(NVARCHAR2->VARCHAR2)型別
- 你知道 Mysql Varchar 型別為什麼人們預設設定 255 嗎MySql型別
- excel 整數匯入資料庫轉成varchar型別後多了小數點Excel資料庫型別
- 死磕以太坊原始碼分析之EVM固定長度資料型別表示原始碼資料型別
- mysql儲存資料,varchar型別中的資料變成了科學計數法?MySql型別
- 關於mysql設定varchar 欄位的預設值''和null的區別,以及varchar和char的區別MySqlNull
- 高效能MySQL第四章 Schema與資料型別優化 VARCHAR和CHARMySql資料型別優化
- Oracle 中varchar2 和nvarchar2區別Oracle
- long2varchar 把long轉換為varchar2
- TS資料型別:型別別名/聯合型別/字面量型別/型別推論等綱要資料型別
- MySQL varchar詳解MySql
- 深入char、varchar、text
- 淺談程式語言型別的強型別,弱型別,動態型別,靜態型別型別
- 有夥伴基於 swagger 等介面文件自動生成基礎測試用例 (型別長度空) 嗎Swagger型別
- JavaScript引用型別-Object型別JavaScript型別Object