1. 程式人生 > >Oracle中varchar2型別的欄位長度是按照byte來定義的

Oracle中varchar2型別的欄位長度是按照byte來定義的

很多新手在建資料庫或新增表、欄位時,會這樣忽略一個問題:ORACLE中VARCHAR2型別的欄位長度是按照byte來定義的。如果資料庫使用的字符集是GBK,GB2312或者其他定長字符集的話,這個問題似乎可以被忽略,因為只要把資料庫的欄位長度/2就可以得到你要限制插入該欄位的中文長度了。 但是,如果資料庫的字符集是UTF-8呢,杯具了吧,人家是變長的。

有人說資料庫欄位長度/3,這是一定不可取的,因為UTF-8是變長表示的,平均為3byte表示一個字元,而並不是一定用3byte。

其實人家ORACLE沒這麼笨,本來就可以用字元為單位來定義varchar2的長度的,這個時候需要注意在建表時這樣寫:

    create table ABC_TABLE (A_FIELD varchar2(20 char))  
這個varchar2(20 char)就表示了是用字元為單位來定義了,而預設情況下的varchar2(20)這樣就是位元組!

如果你之前沒考慮到這個問題,而現在遇到了,又想更改你的欄位定義的話,可以這樣寫:

    alter table ABC_TABLE modify (A_FIELD varchar2(20 char))  
但是如果你不確定究竟是怎麼定義的,或者,你想找出所有采用位元組定義長度的欄位,可以試試用這樣的方法:
    select * from user_tab_columns where CHAR_USED='B'  
這裡的CHAR_USED的意思是:如果是字元定義-'C',位元組定義-'B'

如果需要批量修改所有的以位元組數定義的字串長度,需要建立一個類似這樣的儲存過程:

    create or replace procedure pro_fix_varchar as  
    cursor fieldList is  
      select T1.TABLE_NAME,T1.COLUMN_NAME,T1.DATA_LENGTH from USER_TAB_COLUMNS T1  
       left join user_tables T2 on T2.TABLE_NAME=T1.TABLE_NAME  
       where T2.TABLE_NAME is not null  
       and T2.TABLESPACE_NAME='MY_TABLESPACE' --請把這裡修改為你自己的表空間名  
       and CHAR_USED='B';  
    tblName varchar2(2000);  
    fieldName varchar2(2000);  
    dataLen varchar2(10);  
    sqlStr varchar2(2000);  
    cnt integer;  
    BEGIN  
      dbms_output.put_line('begin');  
      cnt:=0;  
      open fieldList;  
      loop  
        fetch fieldList into tblName,fieldName,dataLen;  
        exit when fieldList%notfound;  
        sqlStr:='alter table "'||tblName||'" modify ("'||fieldName||'" varchar2('||dataLen||' char))';  
        execute immediate sqlStr;  
        commit;  
        cnt:=cnt+1;  
      end loop;  
      close fieldList;  
      dbms_output.put_line('fixed '||cnt||' field(s).');  
    end pro_fix_varchar;  
然後呼叫這個儲存過程:
    call pro_fix_varchar(); 





相關推薦

Oraclevarchar2型別長度限制使用問題

為紀念中華人民共和國建軍90週年,特此一篇,以此紀念,我軍威武!!!一、問題背景專案中商品釋出,卻沒有儲存成功。二、問題定位初步判斷向資料庫中儲存時出現了錯誤,檢視日誌檔案,由於日誌檔案過大就採用grep進行搜尋(再一次說明grep 的強大)其中 “ReserveProductService.update”

Oraclevarchar2型別長度按照byte定義

很多新手在建資料庫或新增表、欄位時,會這樣忽略一個問題:ORACLE中VARCHAR2型別的欄位長度是按照byte來定義的。如果資料庫使用的字符集是GBK,GB2312或者其他定長字符集的話,這個問題似乎可以被忽略,因為只要把資料庫的欄位長度/2就可以得到你要限制插入該欄位

Mybatis框架--Ibatis框架踩坑01 -- JavaBigInteger型別問題!

       在Mybatis框架、 Ibatis框架中, 不支援Java中的 java.math.BigInteger 型別欄位, 支援 java.math.BigDecimal 型別欄位。若Java實體類中,使用 java.math.BigInteger 型別欄位,在

查詢Oracle帶有Clob的表的大小

在oracle裡面,由於lob欄位有獨立的lob segment來儲存,所以查詢需要DBA_SEGMENTS S, DBA_INDEXES  2張表結合才可查出結果。 以下是實驗SQL說明: 表名:GJ_NORM_POOL 表歸屬使用者名稱:ORACLE

Mybatis處理DB2Blob型別的一種方法

簡單來說,就是把Blob欄位對應的屬性的型別設定為byte[],然後在對映xml中存的時候在該欄位出指定為Blob型別就可以了。 例子 EB_COMM_NEWS表中,CONTENT為BLOB型別 在實體類EbCommNews中,對應的屬性為private byte[] CON

oracle為shape新增索引

表名為oscline,shape欄位的格式為sdo_geometry INSERT INTO USER_SDO_GEOM_METADATA (TABLE_NAME, COLUMN_NAME, DIMINFO, SRID)  VALUES ('OSCLINE', 'shape', &nb

Sql Server資料庫Identity型別的使用

大家在建立資料庫的時候肯定是經常使用Identity標識欄位型別的。下面就介紹兩個使用這種型別欄位的小技巧。 1.讓標識欄位從指定的數字開始計數: DBCC checkident (TableName,reseed,計數值-1) 如:讓customers表重新從1開始計數 d

記錄問題:mysqldatetime型別在後臺讀取與前端展示

1.資料庫欄位型別為datetime,model裡:@Column(name = "createtime", length = 20) private Date createTime;2.兩種將資料傳到前端的方法方法一:List<Map<String, Objec

解決在資料庫timestamp型別輸出在頁面上多餘的“.0”

在資料庫中createtime為timestamp型別,資料中的建立時間是沒有後綴'.0',傳到網頁上就出現'.0',在後臺程式碼中更改時間格式。程式碼實現:                  for (ExamRecords examRecords : examRecord

Oracle怎麼檢查 是否包含 ' 單引號

1、用chr函式,找到單引號的assciiSQL> select * from test1 where description like '%'||chr(39)||'%';         ID DESCRIPTION----------- ------------

OracleNUMBER型別不指定長度和小數點精度與指定的區別!

在Oracle中Number型別可以用來儲存0,正負定點或者浮點數,可表示的資料範圍在  1.0 * 10(-130) —— 9.9...9 * 10(125) {38個9後邊帶88個0}的數字,當Oracle中的數學表示式的值>=1.0*10(126)時,Oracle

oracle字元型按數字排序

今天在轉換資料時,遇到了一個主鍵排序的問題。字元型的主鍵,儲存的都是數字,資料導過來以後發現數據排序都是亂的,就想著按數字規則排序。 但發現to_number總是報錯,就想著裡面應該是有字元存在。後來使用了正則關係式,問題解決。 以下是正則關係式的兩種用法,記錄下來。 se

oracle按指定排序刪除重複記錄

       今天看了一下專案上的DBA針對某一模組中的業務寫的儲存過程,裡面資料清洗的過程中時常會進行排重操作,自己總結了一下oracle中排重的思路1,使用rowid來作為限制條件排重rowid與rownum的區別兩者都是偽列,rowid是物理結構上的,而rownum是邏

Oracle查詢某不為空或者為空的SQL語句怎麼寫

比如 insert into table a (a1,b1)values("a1",''); 對於這種情況,因為表裡存的是”,其實是沒有內容的,要查詢這個欄位,不能直接使用 select * from a where b1=''; sql中判斷非

MySQL資料庫tinyint型別讀取資料為true和false

vertx jdbc 取myaql資料也存在這樣的問題,按照如下在進行sql語句編寫時候加上*1就i可以了 今天遇到這麼一個問題,公司最近在做一個活動,然後資料庫需要建表,其中有個欄位是關於獎勵發放的狀態的欄位,結果讀取出來的值為true 一、解決讀取資料為true/

Incorrect datetime value: '' for column Mysql5.6 datetime 型別的插入問題

在5.0.45-community-nt-log中能正常執行的SQL,在5.6.21中不正常。 1. 1檢視資料庫版本 mysql> select database(), version(); +------------+-----------------------

MySQLfloat型別的顯示問題

由於受到版本和平臺的限制,同樣的SQL在不同的平臺上執行的結果可能會不一致。 影響:1. mysql在升級或遷移時可能會導致float型別的資料發生變化。 2. mysqldump建立的備份在slave上進行恢復,可能會遇到float型別的資料在master和slave上

設定oracle的blob,將xml檔案寫入到資料庫

http://hi.baidu.com/net1979/blog/item/1829e14ee7d26c0db2de0569.html可以將二進位制大物件 (BLOB) 作為二進位制或字元資料寫入資料庫,具體視資料來源的

ruby布林型別的非空校驗

無法用validate_presence_of來對boolean型別欄位進行非空校驗 migration程式碼 class CreateCorporateFinancials < ActiveRecord::Migration def self

oracle去掉資料庫的換行符、回車符、製表符小結

        在專案上線後,使用者使用過程中,發現根據物資編碼條件查詢時,資料庫中沒有對應資料,根據分析後,最終確認為資料庫的換行符問題,下面就oracle中去掉資料庫欄位中的換行符、回車符、製表符做小結:      一、特殊符號ascii定義: