1. 程式人生 > >Oracle中生成GUID型別

Oracle中生成GUID型別

     Oracle8i引入了SYS_GUID這個概念,它同Oracle管理員所使用的傳統的序列(sequence)相比具有諸多優勢。一個序列生成器只是簡單地建立從給定的起點開始的一系列整數值,而且它被用在選擇陳述式的時候自動地遞增該系列。 
   
  序列生成器所生成的數字只能保證在單個例項裡是唯一的,這就不適合將它用作並行或者遠端環境裡的主關鍵字,因為各自環境裡的序列可能會生成相同的數字,從而導致衝突的發生。SYS_GUID會保證它建立的識別符號在每個資料庫裡都是唯一的。 
   
  此外,序列必須是DML陳述式的一部分,因此它需要一個到資料庫的往返過程(否則它就不能保證其值是唯一的)。SYS_GUID源自不需要對資料庫進行訪問的時間戳和機器識別符號,這就節省了查詢的消耗。 
  create table use_seq_table(id integer); 
  create sequence use_seq_sequence; 
  insert into use_seq_table values (use_seq_sequence_value.nextval); 
   
  REM - for some reason, the documentation uses raw(32) 
  create table use_guid_table(id raw(16)); 
  insert into use_guid_table(sys_guid());  

     很多應用程式都依靠序列生成器來建立資料行的主關鍵字,這些資料行沒有一個明顯的主值,這也就是說,在這樣的資料集裡一條記錄的建立就會讓資料列發生改變。因此,管理員可能會對在表格中將SYS_GUID用作主關鍵字而不使用序列數感興趣。這在物件在不同機器的不同資料庫裡生成以及需要在後來合併到一起的情況下很有用。 
   

  但是,SYS_GUID所生成的值是一個16位的原始值。序列所生成的整數不會使用16位(的值),除非它達到了10的30次方(每個位元組有兩位),而且數字是相當獨特的: 

  SQL> select dump(123456789012345678901234567890) from dual; 
   
  DUMP(123456789012345678901234567890) 
  -------------------------------------------------------------- 
  Typ=2 Len=16: 207,13,35,57,79,91,13,35,57,79,91,13,35,57,79,91 

較短的值就意味著用於表格和索引的儲存空間更少,以及查詢訪問的時間更短。 
   
  使用SYS_GUID或者序列會在資料庫使用週期裡的某些地方造成效能上的消耗;問題就是在哪裡。對於SYS_GUID而言,效能上的影響在查詢時間和建立時間上(在表格裡要建立更多的塊和索引以容納資料)。對序列而言,效能上的影響在查詢期間,在這個時候,SGA序列的緩衝區被用光。在預設情況下,一個序列一次會緩衝20個值。如果資料庫沒有使用這些值就關閉了,它們就會被丟失。 
   
  SYS_GUID生成的值的另一個顯著的不足之處是,管理這些值會變得困難得多。你必須(手動)輸入它們或者通過指令碼來填充它們,或者將它們作為Web引數來傳遞。 
   
  出於這些原因,將SYS_GUID作為一個主關鍵字不是一個很好主意,除非是在一個並行的環境裡或者希望避免使用管理序列生成器的情況下。 
 


     在這裡,我們不討論 guid和序列器的優勢,每個都會有特定環境下的需求。在Oracle9i和Oracle 10g 裡SYS_GUID產生得到的資料是32 位的,如:234E45F0077881AAE0430AA3034681AA


     我這裡要做的功能是將guid分割成為 Windows系統 ObjectId 的格式:{8-4-4-4-12} ,下面給出兩種解決方法:


方法一:利用substr進行分割,非常簡單,具體程式碼如下:

/** 
 * 建立系統Object Id 格式的字串,返回的結果如下:{234E45F0-077A-81AA-E043-0AA3034681AA} 
 */ 
function CreateGUID  return varchar2 
  is 
guid varchar(64); 
begin 
  guid := SYS_GUID(); 
  return 
  '{'||substr(guid,1,8)||'-'||substr(guid,9,4)|| 
  '-'||substr(guid,13,4)||'-'||substr(guid,17,4) 
  ||'-'||substr(guid,21,12)||'}'; 
end CreateGUID;

方法二:利用CONCAT函式進行連線,具體程式碼如下:
CREATE OR REPLACE FUNCTION GET_GUID
   RETURN CHAR
IS
   v_guid              CHAR (36);
   v_guid_part_one     CHAR (8);
   v_guid_part_two     CHAR (4);
   v_guid_part_three   CHAR (4);
   v_guid_part_four    CHAR (4);
   v_guid_part_five    CHAR (12);
BEGIN
   SELECT SYS_GUID ()
     INTO v_guid
     FROM DUAL;

   v_guid_part_one := SUBSTR (v_guid, 0, 8);
   v_guid_part_two := SUBSTR (v_guid, 8, 4);
   v_guid_part_three := SUBSTR (v_guid, 12, 4);
   v_guid_part_four := SUBSTR (v_guid, 16, 4);
   v_guid_part_five := SUBSTR (v_guid, 20, 12);
   v_guid :=
      CONCAT
         (CONCAT
             (CONCAT
                 (CONCAT (CONCAT (CONCAT (CONCAT (CONCAT (v_guid_part_one,
                                                          '-'),
                                                  v_guid_part_two
                                                 ),
                                          '-'
                                         ),
                                  v_guid_part_three
                                 ),
                          '-'
                         ),
                  v_guid_part_four
                 ),
              '-'
             ),
          v_guid_part_five
         );
   RETURN (v_guid);
END GET_GUID; 


轉載自:http://www.cnblogs.com/dongqi/archive/2008/10/13/1310185.html