国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數據庫 > Oracle > 正文

oracle中使用ANYDATA列對數據串行化方法

2024-08-29 13:41:01
字體:
來源:轉載
供稿:網友

  Oracle版本9提供了一種有趣的新的數據類型,開發人員借助此類型可以聲明包括任何類型數據的變量。對于單個數據來說,此數據類型即ANYDATA。對于TABLE或者VARRAY數據來說,則為ANYDATASET。ANYTYPE用于描述存儲在ANYDATA或者ANYDATASET變量以及欄中的數據類型。 這些數據類型對于處理存儲在數據庫中的xml數據或高級序列(Advanced Queues)具有非常重要的意義。說明文檔中提到了ANYDATA數據類型可以用于對對象進行串行化(serialize),但與之相關的示例較少。
  
  串行化首先將數據值和其他結構(strUCture)組成為另外一些結構,然后將生成的結構的所有構成成分輸出為流。流可以被結構返回讀取,并且將覆蓋前一個會話的信息。通常而言,在應用程序中進行的保存和打開文件的操作即不過是串行化的一種形式。
  
  一個Oracle數據庫或許需要使用串行化功能來存儲一些表格數據的某個版本備份,這樣可以在不使用數據庫提交(commits)、回滾(rollbacks)、回閃(Flashback)查詢的情況下對數據進行查看和其他操作。許多應用程序都會用到類似的對數據源的控制功能,諸如可以在應用級對當前和以前的數據版本進行比較,或對合并操作(merge)和撤銷操作(undo)所產生數據改變進行比較。很多此類應用程序都被設計為對每個表格創建一個備份表格。而對于數據庫性能和開發進度來說,要維護這些眾多的備份表格以及之間的各種關系,成為了生產數據(PRoduction data)以外的沉重負擔。
  
  而通過ANYDATA數據類型以及動態SQL功能,使得通過單一的串行化存儲進程來把許多需要備份的表格串行輸入到一個單獨的備份表格成為可能。ANYDATA的一個優勢在于,不同于類似VARCHAR2的簡單的轉換數據類型,使用ANYDATA方法原始的數據類型并不會丟失。數據可以被存儲在ANYDATA欄或者變量中而不會丟失任何細節(或根據在DATA和VARCHAR2之間進行轉換的當前NLS語義而定)。這些存儲的數據在轉化過程中不會有任何損失。
  
  一個ANYDATA對象可以通過使用任何Convert*方法構造簡單值的方法來實現,或者通過“piecewise”構造方法創建諸如對象和數據庫一類的更為復雜的變量。對于本例而言,我將集中解釋如何使用Convert*方法。
  
  為了創建一個串行化進程,我使用了動態SQL來產生一個對表格中所有數據的查詢命令,其中包括ROWID。然后我將查詢命令進行分解并描述,從而得到一個關于欄和數據類型的列表。再定義提取(fetch)出欄,將每一欄從各行中提取出來,然后將其插入到串行化表格中。在本例中我使用了DBMS_SQL,因為“自身動態SQL(native dynamic SQL)”現在還不能支持描述動態查詢。絕大多數的工作都是對從DBMS_SQL數據類型代碼到合適的數據類型方法以及函數的轉換過程進行處理。要得到這些代碼的列表,可以查看OCI包含文件ocidfn.h,或者是諸如USER_TAB_COLUMNS這樣的對查看(view)的定義。在本例中,我使用了簡單的數據類型(可以在EMP和DEPT表格中找到),這樣可以直接對其進行轉換。
  
  drop table serialized_data;
  
  create table serialized_data
  
  (
  
    tablename varchar2(30) not null,
  
    row_id rowid not null,
  
    colseq integer not null,
  
    item anydata
  
  );
  
  create or replace procedure serialize(p_tablename varchar2)
  
  is
  
    l_tablename varchar2(30) := upper(p_tablename);
  
    c      pls_integer;    -- cursor
  
    x      pls_integer;    -- dummy
  
    col_cnt   pls_integer;
  
    dtab    dbms_sql.desc_tab;
  
    l_rowid   char(18);
  
    l_anydata  anydata;
  
    l_vc2    varchar2(32767);
  
    l_number  number;
  
    l_vc    varchar(32767);
  
    l_date   date;
  
    l_raw    raw(32767);
  
    l_ch    char;
  
    l_clob   clob;
  
    l_blob   blob;
  
    l_bfile   bfile;
  
  begin
  
    c := dbms_sql.open_cursor;
  
    dbms_sql.parse(c,'select rowid,'p_tablename'.* from 'p_tablename,
  
      dbms_sql.native);
  
    dbms_sql.describe_columns(c,col_cnt,dtab);
  
    dbms_sql.define_column(c,1,l_rowid,18);
  
    for i in 2 .. col_cnt loop
  
      case dtab(i).col_type
  
      when 1 then
  
        dbms_sql.define_column(c,i,l_vc2,dtab(i).col_max_len);
  
      when 2 then
  
        dbms_sql.define_column(c,i,l_number);
  
      when 9 then
  
        dbms_sql.define_column(c,i,l_vc,dtab(i).col_max_len);
  
      when 12 then
  
        dbms_sql.define_column(c,i,l_date);
  
      when 23 then
  
        dbms_sql.define_column_raw(c,i,l_raw,dtab(i).col_max_len);
  
      when 96 then
  
        dbms_sql.define_column_char(c,i,l_ch,dtab(i).col_max_len);
  
      when 112 then
  
        dbms_sql.define_column(c,i,l_clob);
  
      when 113 then
  
        dbms_sql.define_column(c,i,l_blob);
  
      when 114 then
  
        dbms_sql.define_column(c,i,l_bfile);
  
      end case;
  
    end loop;
  
    x := dbms_sql.execute(c);
  
    while dbms_sql.fetch_rows(c) != 0 loop
  
      dbms_sql.column_value(c,1,l_rowid);
  
      for i in 2 .. col_cnt loop
  
        case dtab(i).col_type
  
        when 1 then
  
          dbms_sql.column_value(c,i,l_vc2);
  
          l_anydata := ANYDATA.ConvertVarchar2(l_vc2);
  
        when 2 then
  
          dbms_sql.column_value(c,i,l_number);
  
          l_anydata := ANYDATA.ConvertNumber(l_number);
  
        when 9 then
  
          dbms_sql.column_value(c,i,l_vc);
  
          l_anydata := ANYDATA.ConvertVarchar(l_vc);
  
        when 12 then
  
          dbms_sql.column_value(c,i,l_date);
  
          l_anydata := ANYDATA.ConvertDate(l_date);
  
        when 23 then
  
          dbms_sql.column_value(c,i,l_raw);
  
          l_anydata := ANYDATA.ConvertRaw(l_raw);
  
        when 96 then
  
          dbms_sql.column_value(c,i,l_ch);
  
          l_anydata := ANYDATA.ConvertChar(l_ch);
  
        when 112 then
  
          dbms_sql.column_value(c,i,l_clob);
  
          l_anydata := ANYDATA.ConvertClob(l_clob);
  
        when 113 then
  
          dbms_sql.column_value(c,i,l_blob);
  
          l_anydata := ANYDATA.ConvertBlob(l_blob);
  
        when 114 then
  
          dbms_sql.column_value(c,i,l_bfile);
  
          l_anydata := ANYDATA.ConvertBFile(l_bfile);
  
        end case;
  
        insert into serialized_data (tablename,row_id,colseq,item)
  
          values (l_tablename,l_rowid,i,l_anydata);
  
      end loop;
  
    end loop;
  
    dbms_sql.close_cursor(c);
  
  end;
  
  /
  
  show errors;
  
  假如我希望對“EMP”和“DEPT”表格串行化,我可以按照以下代碼通過SQL*Plus來完成:
  
  exec serialize('emp');
  
  exec serialize('dept');
  
  select t.item.gettypename() from serialized_data t;
  
  使用ANYDATA中的一個問題是,假如是對象,則只有很少的信息可以通過直接SQL恢復過來。
表格數據必須使用PL/SQL過程進行訪問。為了表明這點,我將回過頭來對原始表格中的一欄和串行化表格中的一欄進行比較。我可以使此匿名PS/SQL代碼段如下表示:
  
  Declare
  
    l_anydata  anydata;
  
    l_vc2  varchar2(32767);
  
    x    pls_integer;
  
  begin
  
    for row in
  
    (
  
      select emp.ename,sd.item
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 田阳县| 靖远县| 沐川县| 云浮市| 巧家县| 贞丰县| 开化县| 油尖旺区| 日土县| 安塞县| 万年县| 汽车| 漾濞| 彩票| 云霄县| 鄂伦春自治旗| 汶川县| 万年县| 广东省| 来宾市| 洪雅县| 呼玛县| 泾川县| 仙居县| 全南县| 内乡县| 南和县| 永城市| 化州市| 政和县| 霞浦县| 三明市| 金寨县| 商丘市| 呼伦贝尔市| 绵阳市| 云霄县| 冕宁县| 中阳县| 永仁县| 翼城县|