2012-06-25 100 views
3

有沒有一種類型或方式如何在二進制級別的數據存儲在oracle中。 我對dml在table和pl/sql的操作感興趣。oracle二進制數據類型

當前所有的二進制元素都是以varchar2(1000)='11111 ... 0000.1111'的形式存儲的,但是操作和數據存儲容量相當大,因此需要一些優化解決方案。如果這些數據可以以二進制格式存儲,則需要1000/8字節 (具有> 700mln記錄)

也許解決方案是使用某種java + oracle組合來執行這些操作。

想法和建議歡迎。

+1

如果您想要二進制操作(bitand等),請參閱http://stackoverflow.com/questions/6125055/oracle-type-casting/6127701#6127701 – tbone

+0

Oracle數據類型'RAW'是要走的路。過去我使用這種數據類型來存儲和處理4字節(32位)以及16字節(128位)值。請參閱Vincent Malgrat的回答,我不會發表重複他所說的話的答案。你可以用'NUMBER'數據類型來玩一些遊戲,但它有限制,結果會變得更麻煩。 「BLOB」數據類型可以讓您獲得更長的優勢,但同樣,它更麻煩。 'RAW'數據類型真的是要走的路。 – spencer7593

+0

@ spencer7593,只有現在我看到您的意見。使用'HEXTORAW'是最好的解決方案。如果您要添加一個答案,說OP應該首先將'10101010'字符串轉換爲一個十六進制字符串,然後使用hextoraw將它們插入原始數據類型 - 我會對它進行調整。它不使用有問題的轉換爲字符,但它會使它的一個字節長度 –

回答

-1

我不知道這會有所幫助,但你可以USEA NUMBER數據類型和bin_to_num功能:

create table test_bin(num_val number, var_val varchar2(1000)); 

insert into test_bin values(bin_to_num(1,0,1,0,1,0,1,0), '10101010'); 

select dump(num_val, 17) n, dump(var_val, 17) v from test_bin; 

n      | v 
--------------------------------------------------- 
Typ=2 Len=3 c2,^B,G | Typ=1 Len=8 1,0,1,0,1,0,1,0 

正如你所看到的,這是分揀機 - 你只有3而不是8個字節,但它仍然是不是一個字節

UPDATE 發現了一個辦法把它在一個字節: 可以使用chr功能

select dump(chr(bin_to_num(1,0,1,0,1,0,1,0))) c from dual; 

n     
-------------------- 
Typ=1 Len=1 170 

所以,你可以繼續使用VARCHAR2只是每8位轉換爲char

+0

謝謝A.B.Cade ......這也是我的想法,只是我的解決方案是將8/16長度的bin數據解碼爲我自己的字母。 –

+0

對此只有一個問題: 從雙重 中選擇長度('a'|| chr(254)||'a')是否有解釋?因爲我想將一些字符串轉換爲字符是11111101或11111110(以及該死的如何添加br,因爲在ff 2空格不起作用) –

+0

ascii表只能達到127,所以必須使用7位,所以至少一個壓縮7 –

2

爲此,您可以使用BLOB(二進制大對象)類型。 Link舉例說明如何使用它。

+0

嗨,blob是好的,但它會需要8位,並將其存儲爲1個字節? 二進制操作怎麼樣? –

+2

@SauliusS:當然8bit會做一個字節,你想要一個字節的位數不同嗎? –

+0

馬,問題是在blob:='10101010'我的尺寸是db 1字節或8字節?vsize爲blob不起作用 –

8

如果要將二進制數據存儲到4000字節,請使用RAW數據類型。數據將以字符串形式存儲,無需字符集轉換。使用包執行RAWs的操作。

不推薦使用LONG RAW數據類型,當您需要處理超過4000個字節的數據時,應該切換到BLOB

+1

我已經使用'RAW'數據類型來存儲和處理4字節和16字節(32位和128位)二進制值,'RAWTOHEX'和'HEXTORAW'功能可以方便地顯示和更新來自交互式客戶端(如TOAD)的RAW值,在這種交互式客戶端中,使用字符串更容易。我會注意到大部分檢索和維護存儲的RAW值是用PL/SQL。RAW的最大優點是i s字符集轉換不是問題,8個邏輯位用1個字節的存儲空間表示。 – spencer7593

6

見文森特的Malgrat的回答是:如果你想存儲和Oracle進程的二進制數據,那麼RAW數據類型是要走的路。 (如果你的意圖是存儲和檢索圖像,視頻,音頻或壓縮數據,這些數據不需要在數據庫中「處理」,但你只是「存儲」它,並且不需要在數據庫中「處理」,則alegen的答案暗示, 「檢索」它,則BLOB數據類型可能更適合;

(注:RAW數據類型被限制爲4000個字節,該BLOB數據類型不是對於peformance原因,我寧願使用RAW對於那些值。要短得多(比如200字節或更少),我需要定期訪問這些值。對於很長時間的值,如果很多查詢沒有引用二進制數據,我傾向於傾向於使用BLOB(這完全是由於RAW和的差異在內部存儲:內嵌存儲與單獨的塊,分離行,即適合在一個塊中的行數,等等)

對於你所描述的特定問題,從信息您提供,然後RAW聽起來像要走的路。您指定您擁有1000位的序列,但不清楚它是一個常量還是最大長度,或者是否將更長的二進制數據串分解爲更適合列的更易於管理的塊。 (如果你真的在處理大量的二進制數據,你真的想要避免把它「切碎」成一堆小塊,並將每一塊存儲在一個單獨的行中。這將會更加高效一起儲存它作爲一個單一的BLOB,並用它作爲一個簡單的流工作。

所有這一切是真的要告知是否使用BLOB或RAW你的決定。


這且不說,關於從1和0的VARCHAR2表示(例如'00101010',將每個「bit」存儲爲獨立字符的真實信息轉換爲更有效存儲的二進制表示形式,每個「8位」實數信息要求響一個字節的存儲空間...

Oracle RAW數據類型將使您將8位存儲到單個字節中。也就是說,RAW(125)將存儲相當於您的VARCHAR2(1000)的數據,這將爲您節省每行875個字節(對於SBCS,比使用DBCS時多兩倍)。這將顯着降低存儲需求,爲您提供更多的行,並提供更好的性能。

要將當前存儲爲VARCHAR2的數據轉換爲一個1和0的字符串,我不知道任何內置函數。但是,將自己的函數轉換爲二進制字符串表示形式爲十六進制字符串表示形式非常簡單。之後,您可以使用內置HEXTORAW函數將其轉換爲RAW

下面是一個可用作起點的示例。 (注意:這個函數只是一個例子,當輸入字符串的長度不是8個字符的倍數時,它不能有效地處理這些情況,而且它的行爲是字符串值不是'1'或「0」可能不適合(因爲它是寫的,它把比其他任何字符「0」,就好像它是一個「1」。但是,它作爲一個起點不夠好)。

create or replace function binstr_to_hexstr 
(as_binstr in varchar2) return varchar2 
is 
    li_n binary_integer default 0; 
    ls_hexstr varchar2(16) default 'ABCDEF'; 
    ls_return varchar2(2000) default ''; 
begin 
    if (as_binstr is null) then 
    return null; 
    end if; 
    ls_return := ''; 
    li_n := 0; 
    for i in 1 .. length(as_binstr) loop 
    li_n := li_n*2 + abs(instr('01',substr(as_binstr,i,1))-1); 
    if mod(i,4) = 0 then 
     ls_return := ls_return || substr(ls_hexstr,li_n+1,1); 
     li_n := 0; 
    end if; 
    end loop; 
return ls_return; 
end; 
/

SELECT binstr_to_hexstr('00101010') AS hexstr FROM DUAL UNION ALL 
SELECT binstr_to_hexstr('00x0 010') FROM DUAL; 

HEXSTR                    
------ 
2A 
2A 

注意:僅當輸入字符串的長度爲8的偶數倍時(即MOD(length(as_binstr),8) = 0),此函數纔會返回預期結果(匹配的十六進制表示形式)。否則,函數「丟失」尾隨位和/或返回奇數個十六進制數字(功能上可被修飾以拋出異常時,輸入參數的長度不是8的倍數)

HEXTORAWRAWTOHEX功能與RAW數據工作使用客戶端應用程序時,如TOAD,SQL開發是有用的或SQL * Plus。 (該HEXTORAW功能是什麼,我們會使用到的輸出轉換從binstr_to_hexstr功能,RAW。)例如:

create or replace function binstr_to_raw 
(as_binstr in varchar2) return raw 
is 
begin 
    return hextoraw(binstr_to_hexstr(as_binstr)); 
end; 
/

文森特的Malgrat在他的回答中指出,甲骨文提供了一包(如UTL_RAWUTL_ENCODE),它們在處理RAW數據時很有用。

http://docs.oracle.com/cd/E11882_01/appdev.112/e25788/u_raw.htm

+1

+1這就是完整的答案 –

2

截至今天,我和這個工作在10和11g,我想答案是否需要更新。這些數據的內置數據類型是RAW(在PL/SQL中,可以比使用BLOB更容易操作的二進制數據)。

顧名思義,RAW數據類型是原始二進制格式,並且按原樣存儲(第一個塊的長度字節除外),因此是此行的最佳存儲空間。 RAW數據類型可以使用SYS.UTL_RAW包進行操作。它可以鑄造到幾乎任何數據類型(如存儲方案相匹配。比如b1101不是NUMBER 13,但它是PL_INTEGER 13和VARCHAR2 equivalant的CHR(13)

而且,容易做,而不是鑄造用UTL_RAW,的HEXTORAWRAWTOHEX功能從VARCHAR2數據的十六進制表示投數據來回RAW例如,HEXTORAW('d')HEXTORAW('D')兩個結果中的b00001101一個RAW值;你看,額外的零被填充到左側,以形成由於RAW的基本塊是一個字節。在轉換爲VARCHAR2和其他流期間,數據本身作爲小尾數(意味着最低有效字節駐留在數據的最右側字節),但在轉換爲複雜數據類型(如NUMBER)時,它只會複製內存,並帶有填充如果需要的話,向左移動零。